Harden how the compiler references GC objects
authorsbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 Jan 2017 23:50:58 +0000 (23:50 +0000)
committersbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 Jan 2017 23:50:58 +0000 (23:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=167277
<rdar://problem/30179506>

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

Since r210971, the DFG/FTL will flash safepoints before
each phase. This means that there are more opportunities for
a GC to happen while the compiler is running. Because of this,
the compiler must keep track of all the heap pointers that are part
of the Graph data structure. To accomplish this, I've designed
a new type called RegisteredStructure that can only be constructed
after the Graph becomes aware of its underlying Structure*. I
designed this new type to have the type system in C++ help us catch
errors where we're not informing the graph/plan of a heap pointer.
I've made it a compile error to create an OpInfo with a pointer
T* where T inherits from HeapCell. This encourages an OpInfo
to be created with either a FrozenValue* or a RegisteredStructure.
I've added similar compile time assertions for TrustedImmPtr in DFG::SpeculativeJIT
and FTL::Output::constIntPtr. These static asserts don't save us from all bad
programs because there are ways to write code that's incorrect that compiles,
but the new types do help us ensure that the most obvious way of writing the
code is correct.

The reason this patch is so big is that I've strung RegisteredStructure and
RegisteredStructureSet through the entire DFG/FTL.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::determineLiveness):
* bytecode/StructureSet.cpp:
(JSC::StructureSet::filter): Deleted.
(JSC::StructureSet::filterArrayModes): Deleted.
(JSC::StructureSet::speculationFromStructures): Deleted.
(JSC::StructureSet::arrayModesFromStructures): Deleted.
(JSC::StructureSet::validateReferences): Deleted.
* bytecode/StructureSet.h:
* dfg/DFGAbstractInterpreter.h:
(JSC::DFG::AbstractInterpreter::filter):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::booleanResult):
(JSC::DFG::isToThisAnIdentity):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::observeTransition):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::filter):
* dfg/DFGAbstractValue.cpp:
(JSC::DFG::AbstractValue::set):
(JSC::DFG::AbstractValue::setType):
(JSC::DFG::AbstractValue::mergeOSREntryValue):
(JSC::DFG::AbstractValue::filter):
(JSC::DFG::AbstractValue::changeStructure):
(JSC::DFG::AbstractValue::contains):
* dfg/DFGAbstractValue.h:
(JSC::DFG::AbstractValue::observeTransition):
(JSC::DFG::AbstractValue::TransitionObserver::TransitionObserver):
* dfg/DFGArgumentsEliminationPhase.cpp:
* dfg/DFGArrayMode.cpp:
(JSC::DFG::ArrayMode::alreadyChecked):
* dfg/DFGArrayifySlowPathGenerator.h:
(JSC::DFG::ArrayifySlowPathGenerator::ArrayifySlowPathGenerator):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
(JSC::DFG::ByteCodeParser::load):
(JSC::DFG::ByteCodeParser::handleGetById):
(JSC::DFG::ByteCodeParser::handlePutById):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
* dfg/DFGCallArrayAllocatorSlowPathGenerator.h:
(JSC::DFG::CallArrayAllocatorSlowPathGenerator::CallArrayAllocatorSlowPathGenerator):
(JSC::DFG::CallArrayAllocatorWithVariableSizeSlowPathGenerator::CallArrayAllocatorWithVariableSizeSlowPathGenerator):
* dfg/DFGCallCreateDirectArgumentsSlowPathGenerator.h:
(JSC::DFG::CallCreateDirectArgumentsSlowPathGenerator::CallCreateDirectArgumentsSlowPathGenerator):
* dfg/DFGCommonData.cpp:
(JSC::DFG::CommonData::notifyCompilingStructureTransition):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
(JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
(JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
(JSC::DFG::ConstantFoldingPhase::addBaseCheck):
(JSC::DFG::ConstantFoldingPhase::addStructureTransitionCheck):
* dfg/DFGDesiredWeakReferences.cpp:
(JSC::DFG::DesiredWeakReferences::reallyAdd):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::checkArray):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::Graph):
(JSC::DFG::Graph::dump):
(JSC::DFG::Graph::tryGetConstantProperty):
(JSC::DFG::Graph::inferredValueForProperty):
(JSC::DFG::Graph::visitChildren):
(JSC::DFG::Graph::freeze):
(JSC::DFG::Graph::registerStructure):
(JSC::DFG::Graph::assertIsRegistered):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::registerStructure):
(JSC::DFG::Graph::addStructureSet):
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::branchWeakStructure):
* dfg/DFGMultiGetByOffsetData.cpp:
(JSC::DFG::MultiGetByOffsetCase::dumpInContext):
* dfg/DFGMultiGetByOffsetData.h:
(JSC::DFG::MultiGetByOffsetCase::MultiGetByOffsetCase):
(JSC::DFG::MultiGetByOffsetCase::set):
* dfg/DFGNode.cpp:
(JSC::DFG::Node::convertToPutStructureHint):
* dfg/DFGNode.h:
(JSC::DFG::Node::convertToCheckStructure):
(JSC::DFG::Node::structureSet):
(JSC::DFG::Node::structure):
(JSC::DFG::Node::OpInfoWrapper::OpInfoWrapper):
(JSC::DFG::Node::OpInfoWrapper::operator=):
(JSC::DFG::Node::OpInfoWrapper::asRegisteredStructure):
* dfg/DFGObjectAllocationSinkingPhase.cpp:
* dfg/DFGOpInfo.h:
(JSC::DFG::OpInfo::OpInfo):
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
(JSC::DFG::Plan::finalizeWithoutNotifyingCallback):
* dfg/DFGRegisteredStructure.h: Added.
(JSC::DFG::RegisteredStructure::get):
(JSC::DFG::RegisteredStructure::operator->):
(JSC::DFG::RegisteredStructure::operator==):
(JSC::DFG::RegisteredStructure::operator!=):
(JSC::DFG::RegisteredStructure::operator bool):
(JSC::DFG::RegisteredStructure::RegisteredStructure):
(JSC::DFG::RegisteredStructure::createPrivate):
* dfg/DFGRegisteredStructureSet.cpp: Added.
(JSC::DFG::RegisteredStructureSet::filter):
(JSC::DFG::RegisteredStructureSet::filterArrayModes):
(JSC::DFG::RegisteredStructureSet::speculationFromStructures):
(JSC::DFG::RegisteredStructureSet::arrayModesFromStructures):
(JSC::DFG::RegisteredStructureSet::validateReferences):
* dfg/DFGRegisteredStructureSet.h: Added.
(JSC::DFG::RegisteredStructureSet::RegisteredStructureSet):
(JSC::DFG::RegisteredStructureSet::onlyStructure):
(JSC::DFG::RegisteredStructureSet::toStructureSet):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::emitAllocateRawObject):
(JSC::DFG::SpeculativeJIT::emitGetCallee):
(JSC::DFG::SpeculativeJIT::silentFill):
(JSC::DFG::SpeculativeJIT::checkArray):
(JSC::DFG::SpeculativeJIT::compileGetByValOnString):
(JSC::DFG::SpeculativeJIT::compileFromCharCode):
(JSC::DFG::SpeculativeJIT::compileDoubleRep):
(JSC::DFG::compileClampDoubleToByte):
(JSC::DFG::SpeculativeJIT::compileMakeRope):
(JSC::DFG::SpeculativeJIT::compileArithRounding):
(JSC::DFG::SpeculativeJIT::compileNewFunctionCommon):
(JSC::DFG::SpeculativeJIT::compileNewFunction):
(JSC::DFG::SpeculativeJIT::compileCreateActivation):
(JSC::DFG::SpeculativeJIT::compileCreateDirectArguments):
(JSC::DFG::SpeculativeJIT::compileCreateScopedArguments):
(JSC::DFG::SpeculativeJIT::compileCreateClonedArguments):
(JSC::DFG::SpeculativeJIT::compileSpread):
(JSC::DFG::SpeculativeJIT::compileArraySlice):
(JSC::DFG::SpeculativeJIT::compileTypeOf):
(JSC::DFG::SpeculativeJIT::compileAllocatePropertyStorage):
(JSC::DFG::SpeculativeJIT::compileReallocatePropertyStorage):
(JSC::DFG::SpeculativeJIT::compileToStringOrCallStringConstructorOnCell):
(JSC::DFG::SpeculativeJIT::compileNewTypedArray):
(JSC::DFG::SpeculativeJIT::speculateStringOrStringObject):
(JSC::DFG::SpeculativeJIT::compileMaterializeNewObject):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::TrustedImmPtr::TrustedImmPtr):
(JSC::DFG::SpeculativeJIT::TrustedImmPtr::weakPointer):
(JSC::DFG::SpeculativeJIT::TrustedImmPtr::operator MacroAssembler::TrustedImmPtr):
(JSC::DFG::SpeculativeJIT::TrustedImmPtr::asIntptr):
(JSC::DFG::SpeculativeJIT::callOperation):
(JSC::DFG::SpeculativeJIT::emitAllocateDestructibleObject):
(JSC::DFG::SpeculativeJIT::speculateStringObjectForStructure):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNullOrUndefined):
(JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNullOrUndefined):
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
(JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNullOrUndefined):
(JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNullOrUndefined):
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
(JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleNode):
* dfg/DFGStructureAbstractValue.cpp:
(JSC::DFG::StructureAbstractValue::assertIsRegistered):
(JSC::DFG::StructureAbstractValue::clobber):
(JSC::DFG::StructureAbstractValue::observeTransition):
(JSC::DFG::StructureAbstractValue::observeTransitions):
(JSC::DFG::StructureAbstractValue::add):
(JSC::DFG::StructureAbstractValue::merge):
(JSC::DFG::StructureAbstractValue::mergeNotTop):
(JSC::DFG::StructureAbstractValue::filter):
(JSC::DFG::StructureAbstractValue::filterSlow):
(JSC::DFG::StructureAbstractValue::filterClassInfoSlow):
(JSC::DFG::StructureAbstractValue::contains):
(JSC::DFG::StructureAbstractValue::isSubsetOf):
(JSC::DFG::StructureAbstractValue::isSupersetOf):
(JSC::DFG::StructureAbstractValue::overlaps):
(JSC::DFG::StructureAbstractValue::isSubClassOf):
(JSC::DFG::StructureAbstractValue::dumpInContext):
* dfg/DFGStructureAbstractValue.h:
(JSC::DFG::StructureAbstractValue::StructureAbstractValue):
(JSC::DFG::StructureAbstractValue::operator=):
(JSC::DFG::StructureAbstractValue::set):
(JSC::DFG::StructureAbstractValue::toStructureSet):
(JSC::DFG::StructureAbstractValue::at):
(JSC::DFG::StructureAbstractValue::operator[]):
(JSC::DFG::StructureAbstractValue::onlyStructure):
* dfg/DFGStructureRegistrationPhase.cpp:
(JSC::DFG::StructureRegistrationPhase::StructureRegistrationPhase): Deleted.
(JSC::DFG::StructureRegistrationPhase::run): Deleted.
(JSC::DFG::StructureRegistrationPhase::registerStructures): Deleted.
(JSC::DFG::StructureRegistrationPhase::registerStructure): Deleted.
(JSC::DFG::StructureRegistrationPhase::assertAreRegistered): Deleted.
(JSC::DFG::StructureRegistrationPhase::assertIsRegistered): Deleted.
(JSC::DFG::performStructureRegistration): Deleted.
* dfg/DFGStructureRegistrationPhase.h:
* dfg/DFGTransition.cpp:
(JSC::DFG::Transition::dumpInContext):
* dfg/DFGTransition.h:
(JSC::DFG::Transition::Transition):
* dfg/DFGTypeCheckHoistingPhase.cpp:
(JSC::DFG::TypeCheckHoistingPhase::noticeStructureCheck):
(JSC::DFG::TypeCheckHoistingPhase::noticeStructureCheckAccountingForArrayMode):
* dfg/DFGValidate.cpp:
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::lower):
(JSC::FTL::DFG::LowerDFGToB3::compileCallObjectConstructor):
(JSC::FTL::DFG::LowerDFGToB3::compileCheckStructure):
(JSC::FTL::DFG::LowerDFGToB3::compilePutStructure):
(JSC::FTL::DFG::LowerDFGToB3::compileArraySlice):
(JSC::FTL::DFG::LowerDFGToB3::compileCreateActivation):
(JSC::FTL::DFG::LowerDFGToB3::compileNewFunction):
(JSC::FTL::DFG::LowerDFGToB3::compileCreateDirectArguments):
(JSC::FTL::DFG::LowerDFGToB3::compileCreateRest):
(JSC::FTL::DFG::LowerDFGToB3::compileNewArray):
(JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSpread):
(JSC::FTL::DFG::LowerDFGToB3::compileNewArrayBuffer):
(JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSize):
(JSC::FTL::DFG::LowerDFGToB3::compileNewTypedArray):
(JSC::FTL::DFG::LowerDFGToB3::compileAllocatePropertyStorage):
(JSC::FTL::DFG::LowerDFGToB3::compileReallocatePropertyStorage):
(JSC::FTL::DFG::LowerDFGToB3::compileMultiGetByOffset):
(JSC::FTL::DFG::LowerDFGToB3::compileMultiPutByOffset):
(JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucket):
(JSC::FTL::DFG::LowerDFGToB3::compileOverridesHasInstance):
(JSC::FTL::DFG::LowerDFGToB3::compileCheckStructureImmediate):
(JSC::FTL::DFG::LowerDFGToB3::compileMaterializeNewObject):
(JSC::FTL::DFG::LowerDFGToB3::compileMaterializeCreateActivation):
(JSC::FTL::DFG::LowerDFGToB3::compileNewRegexp):
(JSC::FTL::DFG::LowerDFGToB3::compileLogShadowChickenTail):
(JSC::FTL::DFG::LowerDFGToB3::checkStructure):
(JSC::FTL::DFG::LowerDFGToB3::checkInferredType):
(JSC::FTL::DFG::LowerDFGToB3::allocateObject):
(JSC::FTL::DFG::LowerDFGToB3::allocateVariableSizedObject):
(JSC::FTL::DFG::LowerDFGToB3::allocateJSArray):
(JSC::FTL::DFG::LowerDFGToB3::allocateUninitializedContiguousJSArray):
(JSC::FTL::DFG::LowerDFGToB3::boolify):
(JSC::FTL::DFG::LowerDFGToB3::equalNullOrUndefined):
(JSC::FTL::DFG::LowerDFGToB3::lowCell):
(JSC::FTL::DFG::LowerDFGToB3::speculateStringObjectForStructureID):
(JSC::FTL::DFG::LowerDFGToB3::weakPointer):
(JSC::FTL::DFG::LowerDFGToB3::frozenPointer):
(JSC::FTL::DFG::LowerDFGToB3::weakStructureID):
(JSC::FTL::DFG::LowerDFGToB3::weakStructure):
(JSC::FTL::DFG::LowerDFGToB3::crash):
* ftl/FTLOutput.h:
(JSC::FTL::Output::weakPointer):
(JSC::FTL::Output::constIntPtr):

Source/WTF:

I made TinyPtrSet use bitwise_cast instead of static_cast
for its singleEntry() function so that it can work on pointer-like
types just as it can on actual pointer types.

An example of where this matters is when you have TinyPtrSet<T>
where T is defined to be a struct which wraps a pointer, e.g:

struct T {
    void* m_pointer;
}

* wtf/TinyPtrSet.h:
(WTF::TinyPtrSet::singleEntry):

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

50 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/StructureSet.cpp
Source/JavaScriptCore/bytecode/StructureSet.h
Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGAbstractValue.cpp
Source/JavaScriptCore/dfg/DFGAbstractValue.h
Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp
Source/JavaScriptCore/dfg/DFGArrayMode.cpp
Source/JavaScriptCore/dfg/DFGArrayifySlowPathGenerator.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h
Source/JavaScriptCore/dfg/DFGCallCreateDirectArgumentsSlowPathGenerator.h
Source/JavaScriptCore/dfg/DFGCommonData.cpp
Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
Source/JavaScriptCore/dfg/DFGDesiredWeakReferences.cpp
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGGraph.cpp
Source/JavaScriptCore/dfg/DFGGraph.h
Source/JavaScriptCore/dfg/DFGJITCompiler.h
Source/JavaScriptCore/dfg/DFGMultiGetByOffsetData.cpp
Source/JavaScriptCore/dfg/DFGMultiGetByOffsetData.h
Source/JavaScriptCore/dfg/DFGNode.cpp
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
Source/JavaScriptCore/dfg/DFGOpInfo.h
Source/JavaScriptCore/dfg/DFGPlan.cpp
Source/JavaScriptCore/dfg/DFGRegisteredStructure.h [moved from Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.h with 60% similarity]
Source/JavaScriptCore/dfg/DFGRegisteredStructureSet.cpp [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGRegisteredStructureSet.h [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGSafeToExecute.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
Source/JavaScriptCore/dfg/DFGStructureAbstractValue.cpp
Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h
Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp [deleted file]
Source/JavaScriptCore/dfg/DFGTransition.cpp
Source/JavaScriptCore/dfg/DFGTransition.h
Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp
Source/JavaScriptCore/dfg/DFGValidate.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/ftl/FTLOutput.h
Source/WTF/ChangeLog
Source/WTF/wtf/TinyPtrSet.h

index a59093e..ff03032 100644 (file)
@@ -373,6 +373,7 @@ set(JavaScriptCore_SOURCES
     dfg/DFGPromotedHeapLocation.cpp
     dfg/DFGPureValue.cpp
     dfg/DFGPutStackSinkingPhase.cpp
+    dfg/DFGRegisteredStructureSet.cpp
     dfg/DFGSSACalculator.cpp
     dfg/DFGSSAConversionPhase.cpp
     dfg/DFGSSALoweringPhase.cpp
@@ -386,7 +387,6 @@ set(JavaScriptCore_SOURCES
     dfg/DFGStoreBarrierInsertionPhase.cpp
     dfg/DFGStrengthReductionPhase.cpp
     dfg/DFGStructureAbstractValue.cpp
-    dfg/DFGStructureRegistrationPhase.cpp
     dfg/DFGThreadData.cpp
     dfg/DFGThunks.cpp
     dfg/DFGTierUpCheckInjectionPhase.cpp
index a83cf6c..4abeb03 100644 (file)
@@ -1,3 +1,284 @@
+2017-01-26  Saam Barati  <sbarati@apple.com>
+
+        Harden how the compiler references GC objects
+        https://bugs.webkit.org/show_bug.cgi?id=167277
+        <rdar://problem/30179506>
+
+        Reviewed by Filip Pizlo.
+
+        Since r210971, the DFG/FTL will flash safepoints before
+        each phase. This means that there are more opportunities for
+        a GC to happen while the compiler is running. Because of this,
+        the compiler must keep track of all the heap pointers that are part
+        of the Graph data structure. To accomplish this, I've designed
+        a new type called RegisteredStructure that can only be constructed
+        after the Graph becomes aware of its underlying Structure*. I
+        designed this new type to have the type system in C++ help us catch
+        errors where we're not informing the graph/plan of a heap pointer.
+        I've made it a compile error to create an OpInfo with a pointer
+        T* where T inherits from HeapCell. This encourages an OpInfo
+        to be created with either a FrozenValue* or a RegisteredStructure.
+        I've added similar compile time assertions for TrustedImmPtr in DFG::SpeculativeJIT
+        and FTL::Output::constIntPtr. These static asserts don't save us from all bad
+        programs because there are ways to write code that's incorrect that compiles,
+        but the new types do help us ensure that the most obvious way of writing the
+        code is correct.
+        
+        The reason this patch is so big is that I've strung RegisteredStructure and
+        RegisteredStructureSet through the entire DFG/FTL.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::determineLiveness):
+        * bytecode/StructureSet.cpp:
+        (JSC::StructureSet::filter): Deleted.
+        (JSC::StructureSet::filterArrayModes): Deleted.
+        (JSC::StructureSet::speculationFromStructures): Deleted.
+        (JSC::StructureSet::arrayModesFromStructures): Deleted.
+        (JSC::StructureSet::validateReferences): Deleted.
+        * bytecode/StructureSet.h:
+        * dfg/DFGAbstractInterpreter.h:
+        (JSC::DFG::AbstractInterpreter::filter):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::booleanResult):
+        (JSC::DFG::isToThisAnIdentity):
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::observeTransition):
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::filter):
+        * dfg/DFGAbstractValue.cpp:
+        (JSC::DFG::AbstractValue::set):
+        (JSC::DFG::AbstractValue::setType):
+        (JSC::DFG::AbstractValue::mergeOSREntryValue):
+        (JSC::DFG::AbstractValue::filter):
+        (JSC::DFG::AbstractValue::changeStructure):
+        (JSC::DFG::AbstractValue::contains):
+        * dfg/DFGAbstractValue.h:
+        (JSC::DFG::AbstractValue::observeTransition):
+        (JSC::DFG::AbstractValue::TransitionObserver::TransitionObserver):
+        * dfg/DFGArgumentsEliminationPhase.cpp:
+        * dfg/DFGArrayMode.cpp:
+        (JSC::DFG::ArrayMode::alreadyChecked):
+        * dfg/DFGArrayifySlowPathGenerator.h:
+        (JSC::DFG::ArrayifySlowPathGenerator::ArrayifySlowPathGenerator):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
+        (JSC::DFG::ByteCodeParser::load):
+        (JSC::DFG::ByteCodeParser::handleGetById):
+        (JSC::DFG::ByteCodeParser::handlePutById):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
+        * dfg/DFGCallArrayAllocatorSlowPathGenerator.h:
+        (JSC::DFG::CallArrayAllocatorSlowPathGenerator::CallArrayAllocatorSlowPathGenerator):
+        (JSC::DFG::CallArrayAllocatorWithVariableSizeSlowPathGenerator::CallArrayAllocatorWithVariableSizeSlowPathGenerator):
+        * dfg/DFGCallCreateDirectArgumentsSlowPathGenerator.h:
+        (JSC::DFG::CallCreateDirectArgumentsSlowPathGenerator::CallCreateDirectArgumentsSlowPathGenerator):
+        * dfg/DFGCommonData.cpp:
+        (JSC::DFG::CommonData::notifyCompilingStructureTransition):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        (JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
+        (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
+        (JSC::DFG::ConstantFoldingPhase::addBaseCheck):
+        (JSC::DFG::ConstantFoldingPhase::addStructureTransitionCheck):
+        * dfg/DFGDesiredWeakReferences.cpp:
+        (JSC::DFG::DesiredWeakReferences::reallyAdd):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::checkArray):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::Graph):
+        (JSC::DFG::Graph::dump):
+        (JSC::DFG::Graph::tryGetConstantProperty):
+        (JSC::DFG::Graph::inferredValueForProperty):
+        (JSC::DFG::Graph::visitChildren):
+        (JSC::DFG::Graph::freeze):
+        (JSC::DFG::Graph::registerStructure):
+        (JSC::DFG::Graph::assertIsRegistered):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::registerStructure):
+        (JSC::DFG::Graph::addStructureSet):
+        * dfg/DFGJITCompiler.h:
+        (JSC::DFG::JITCompiler::branchWeakStructure):
+        * dfg/DFGMultiGetByOffsetData.cpp:
+        (JSC::DFG::MultiGetByOffsetCase::dumpInContext):
+        * dfg/DFGMultiGetByOffsetData.h:
+        (JSC::DFG::MultiGetByOffsetCase::MultiGetByOffsetCase):
+        (JSC::DFG::MultiGetByOffsetCase::set):
+        * dfg/DFGNode.cpp:
+        (JSC::DFG::Node::convertToPutStructureHint):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::convertToCheckStructure):
+        (JSC::DFG::Node::structureSet):
+        (JSC::DFG::Node::structure):
+        (JSC::DFG::Node::OpInfoWrapper::OpInfoWrapper):
+        (JSC::DFG::Node::OpInfoWrapper::operator=):
+        (JSC::DFG::Node::OpInfoWrapper::asRegisteredStructure):
+        * dfg/DFGObjectAllocationSinkingPhase.cpp:
+        * dfg/DFGOpInfo.h:
+        (JSC::DFG::OpInfo::OpInfo):
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::compileInThreadImpl):
+        (JSC::DFG::Plan::finalizeWithoutNotifyingCallback):
+        * dfg/DFGRegisteredStructure.h: Added.
+        (JSC::DFG::RegisteredStructure::get):
+        (JSC::DFG::RegisteredStructure::operator->):
+        (JSC::DFG::RegisteredStructure::operator==):
+        (JSC::DFG::RegisteredStructure::operator!=):
+        (JSC::DFG::RegisteredStructure::operator bool):
+        (JSC::DFG::RegisteredStructure::RegisteredStructure):
+        (JSC::DFG::RegisteredStructure::createPrivate):
+        * dfg/DFGRegisteredStructureSet.cpp: Added.
+        (JSC::DFG::RegisteredStructureSet::filter):
+        (JSC::DFG::RegisteredStructureSet::filterArrayModes):
+        (JSC::DFG::RegisteredStructureSet::speculationFromStructures):
+        (JSC::DFG::RegisteredStructureSet::arrayModesFromStructures):
+        (JSC::DFG::RegisteredStructureSet::validateReferences):
+        * dfg/DFGRegisteredStructureSet.h: Added.
+        (JSC::DFG::RegisteredStructureSet::RegisteredStructureSet):
+        (JSC::DFG::RegisteredStructureSet::onlyStructure):
+        (JSC::DFG::RegisteredStructureSet::toStructureSet):
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::emitAllocateRawObject):
+        (JSC::DFG::SpeculativeJIT::emitGetCallee):
+        (JSC::DFG::SpeculativeJIT::silentFill):
+        (JSC::DFG::SpeculativeJIT::checkArray):
+        (JSC::DFG::SpeculativeJIT::compileGetByValOnString):
+        (JSC::DFG::SpeculativeJIT::compileFromCharCode):
+        (JSC::DFG::SpeculativeJIT::compileDoubleRep):
+        (JSC::DFG::compileClampDoubleToByte):
+        (JSC::DFG::SpeculativeJIT::compileMakeRope):
+        (JSC::DFG::SpeculativeJIT::compileArithRounding):
+        (JSC::DFG::SpeculativeJIT::compileNewFunctionCommon):
+        (JSC::DFG::SpeculativeJIT::compileNewFunction):
+        (JSC::DFG::SpeculativeJIT::compileCreateActivation):
+        (JSC::DFG::SpeculativeJIT::compileCreateDirectArguments):
+        (JSC::DFG::SpeculativeJIT::compileCreateScopedArguments):
+        (JSC::DFG::SpeculativeJIT::compileCreateClonedArguments):
+        (JSC::DFG::SpeculativeJIT::compileSpread):
+        (JSC::DFG::SpeculativeJIT::compileArraySlice):
+        (JSC::DFG::SpeculativeJIT::compileTypeOf):
+        (JSC::DFG::SpeculativeJIT::compileAllocatePropertyStorage):
+        (JSC::DFG::SpeculativeJIT::compileReallocatePropertyStorage):
+        (JSC::DFG::SpeculativeJIT::compileToStringOrCallStringConstructorOnCell):
+        (JSC::DFG::SpeculativeJIT::compileNewTypedArray):
+        (JSC::DFG::SpeculativeJIT::speculateStringOrStringObject):
+        (JSC::DFG::SpeculativeJIT::compileMaterializeNewObject):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::TrustedImmPtr::TrustedImmPtr):
+        (JSC::DFG::SpeculativeJIT::TrustedImmPtr::weakPointer):
+        (JSC::DFG::SpeculativeJIT::TrustedImmPtr::operator MacroAssembler::TrustedImmPtr):
+        (JSC::DFG::SpeculativeJIT::TrustedImmPtr::asIntptr):
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        (JSC::DFG::SpeculativeJIT::emitAllocateDestructibleObject):
+        (JSC::DFG::SpeculativeJIT::speculateStringObjectForStructure):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNullOrUndefined):
+        (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNullOrUndefined):
+        (JSC::DFG::SpeculativeJIT::emitCall):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
+        (JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
+        (JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
+        (JSC::DFG::SpeculativeJIT::compile):
+        (JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNullOrUndefined):
+        (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNullOrUndefined):
+        (JSC::DFG::SpeculativeJIT::emitCall):
+        (JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
+        (JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
+        (JSC::DFG::SpeculativeJIT::compile):
+        (JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):
+        * dfg/DFGStrengthReductionPhase.cpp:
+        (JSC::DFG::StrengthReductionPhase::handleNode):
+        * dfg/DFGStructureAbstractValue.cpp:
+        (JSC::DFG::StructureAbstractValue::assertIsRegistered):
+        (JSC::DFG::StructureAbstractValue::clobber):
+        (JSC::DFG::StructureAbstractValue::observeTransition):
+        (JSC::DFG::StructureAbstractValue::observeTransitions):
+        (JSC::DFG::StructureAbstractValue::add):
+        (JSC::DFG::StructureAbstractValue::merge):
+        (JSC::DFG::StructureAbstractValue::mergeNotTop):
+        (JSC::DFG::StructureAbstractValue::filter):
+        (JSC::DFG::StructureAbstractValue::filterSlow):
+        (JSC::DFG::StructureAbstractValue::filterClassInfoSlow):
+        (JSC::DFG::StructureAbstractValue::contains):
+        (JSC::DFG::StructureAbstractValue::isSubsetOf):
+        (JSC::DFG::StructureAbstractValue::isSupersetOf):
+        (JSC::DFG::StructureAbstractValue::overlaps):
+        (JSC::DFG::StructureAbstractValue::isSubClassOf):
+        (JSC::DFG::StructureAbstractValue::dumpInContext):
+        * dfg/DFGStructureAbstractValue.h:
+        (JSC::DFG::StructureAbstractValue::StructureAbstractValue):
+        (JSC::DFG::StructureAbstractValue::operator=):
+        (JSC::DFG::StructureAbstractValue::set):
+        (JSC::DFG::StructureAbstractValue::toStructureSet):
+        (JSC::DFG::StructureAbstractValue::at):
+        (JSC::DFG::StructureAbstractValue::operator[]):
+        (JSC::DFG::StructureAbstractValue::onlyStructure):
+        * dfg/DFGStructureRegistrationPhase.cpp:
+        (JSC::DFG::StructureRegistrationPhase::StructureRegistrationPhase): Deleted.
+        (JSC::DFG::StructureRegistrationPhase::run): Deleted.
+        (JSC::DFG::StructureRegistrationPhase::registerStructures): Deleted.
+        (JSC::DFG::StructureRegistrationPhase::registerStructure): Deleted.
+        (JSC::DFG::StructureRegistrationPhase::assertAreRegistered): Deleted.
+        (JSC::DFG::StructureRegistrationPhase::assertIsRegistered): Deleted.
+        (JSC::DFG::performStructureRegistration): Deleted.
+        * dfg/DFGStructureRegistrationPhase.h:
+        * dfg/DFGTransition.cpp:
+        (JSC::DFG::Transition::dumpInContext):
+        * dfg/DFGTransition.h:
+        (JSC::DFG::Transition::Transition):
+        * dfg/DFGTypeCheckHoistingPhase.cpp:
+        (JSC::DFG::TypeCheckHoistingPhase::noticeStructureCheck):
+        (JSC::DFG::TypeCheckHoistingPhase::noticeStructureCheckAccountingForArrayMode):
+        * dfg/DFGValidate.cpp:
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::lower):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCallObjectConstructor):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCheckStructure):
+        (JSC::FTL::DFG::LowerDFGToB3::compilePutStructure):
+        (JSC::FTL::DFG::LowerDFGToB3::compileArraySlice):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCreateActivation):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewFunction):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCreateDirectArguments):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCreateRest):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewArray):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSpread):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewArrayBuffer):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSize):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewTypedArray):
+        (JSC::FTL::DFG::LowerDFGToB3::compileAllocatePropertyStorage):
+        (JSC::FTL::DFG::LowerDFGToB3::compileReallocatePropertyStorage):
+        (JSC::FTL::DFG::LowerDFGToB3::compileMultiGetByOffset):
+        (JSC::FTL::DFG::LowerDFGToB3::compileMultiPutByOffset):
+        (JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucket):
+        (JSC::FTL::DFG::LowerDFGToB3::compileOverridesHasInstance):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCheckStructureImmediate):
+        (JSC::FTL::DFG::LowerDFGToB3::compileMaterializeNewObject):
+        (JSC::FTL::DFG::LowerDFGToB3::compileMaterializeCreateActivation):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewRegexp):
+        (JSC::FTL::DFG::LowerDFGToB3::compileLogShadowChickenTail):
+        (JSC::FTL::DFG::LowerDFGToB3::checkStructure):
+        (JSC::FTL::DFG::LowerDFGToB3::checkInferredType):
+        (JSC::FTL::DFG::LowerDFGToB3::allocateObject):
+        (JSC::FTL::DFG::LowerDFGToB3::allocateVariableSizedObject):
+        (JSC::FTL::DFG::LowerDFGToB3::allocateJSArray):
+        (JSC::FTL::DFG::LowerDFGToB3::allocateUninitializedContiguousJSArray):
+        (JSC::FTL::DFG::LowerDFGToB3::boolify):
+        (JSC::FTL::DFG::LowerDFGToB3::equalNullOrUndefined):
+        (JSC::FTL::DFG::LowerDFGToB3::lowCell):
+        (JSC::FTL::DFG::LowerDFGToB3::speculateStringObjectForStructureID):
+        (JSC::FTL::DFG::LowerDFGToB3::weakPointer):
+        (JSC::FTL::DFG::LowerDFGToB3::frozenPointer):
+        (JSC::FTL::DFG::LowerDFGToB3::weakStructureID):
+        (JSC::FTL::DFG::LowerDFGToB3::weakStructure):
+        (JSC::FTL::DFG::LowerDFGToB3::crash):
+        * ftl/FTLOutput.h:
+        (JSC::FTL::Output::weakPointer):
+        (JSC::FTL::Output::constIntPtr):
+
 2017-01-26  JF Bastien  <jfbastien@apple.com>
 
         OSR entry: delay outer-loop compilation when at inner-loop
index 4083f14..7a7fe85 100644 (file)
                0F766D3815AE4A1C008F363E /* StructureStubClearingWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F766D3615AE4A1A008F363E /* StructureStubClearingWatchpoint.cpp */; };
                0F766D3915AE4A1F008F363E /* StructureStubClearingWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D3715AE4A1A008F363E /* StructureStubClearingWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F7700921402FF3C0078EB39 /* SamplingCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7700911402FF280078EB39 /* SamplingCounter.cpp */; };
-               0F79085519A290B200F6310C /* DFGStructureRegistrationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F79085319A290B200F6310C /* DFGStructureRegistrationPhase.cpp */; };
-               0F79085619A290B200F6310C /* DFGStructureRegistrationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F79085419A290B200F6310C /* DFGStructureRegistrationPhase.h */; };
                0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */; };
                0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC0977E1469EBC400CF2442 /* DFGCommon.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F7C39FB1C8F629300480151 /* RegExpInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C39FA1C8F629300480151 /* RegExpInlines.h */; };
                796FB43A1DFF8C3F0039C95D /* JSWebAssemblyHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 796FB4391DFF8C3F0039C95D /* JSWebAssemblyHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; };
                797E07A91B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 797E07A71B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp */; };
                797E07AA1B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 797E07A81B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               7980C16C1E3A940E00B71615 /* DFGRegisteredStructureSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7980C16A1E3A940E00B71615 /* DFGRegisteredStructureSet.cpp */; };
+               7980C16D1E3A940E00B71615 /* DFGRegisteredStructureSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 7980C16B1E3A940E00B71615 /* DFGRegisteredStructureSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
                798937781DCAB57300F8D4FB /* JSFixedArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 798937761DCAB57300F8D4FB /* JSFixedArray.cpp */; };
                798937791DCAB57300F8D4FB /* JSFixedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 798937771DCAB57300F8D4FB /* JSFixedArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
                799EF7C41C56ED96002B0534 /* B3PCToOriginMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 799EF7C31C56ED96002B0534 /* B3PCToOriginMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
                79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EE0BFE1B4AFB85000385C9 /* VariableEnvironment.h */; settings = {ATTRIBUTES = (Private, ); }; };
                79F8FC1E1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79F8FC1C1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.cpp */; };
                79F8FC1F1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 79F8FC1D1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.h */; };
+               79FC8A081E32E9F000D88F0E /* DFGRegisteredStructure.h in Headers */ = {isa = PBXBuildFile; fileRef = 79FC8A071E32E9F000D88F0E /* DFGRegisteredStructure.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7BC547D31B6959A100959B58 /* WasmFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BC547D21B69599B00959B58 /* WasmFormat.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7C008CDA187124BB00955C24 /* JSPromiseDeferred.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C008CD8187124BB00955C24 /* JSPromiseDeferred.cpp */; };
                7C008CDB187124BB00955C24 /* JSPromiseDeferred.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C008CD9187124BB00955C24 /* JSPromiseDeferred.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F766D3715AE4A1A008F363E /* StructureStubClearingWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureStubClearingWatchpoint.h; sourceTree = "<group>"; };
                0F77008E1402FDD60078EB39 /* SamplingCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamplingCounter.h; sourceTree = "<group>"; };
                0F7700911402FF280078EB39 /* SamplingCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SamplingCounter.cpp; sourceTree = "<group>"; };
-               0F79085319A290B200F6310C /* DFGStructureRegistrationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStructureRegistrationPhase.cpp; path = dfg/DFGStructureRegistrationPhase.cpp; sourceTree = "<group>"; };
-               0F79085419A290B200F6310C /* DFGStructureRegistrationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStructureRegistrationPhase.h; path = dfg/DFGStructureRegistrationPhase.h; sourceTree = "<group>"; };
                0F7C39FA1C8F629300480151 /* RegExpInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpInlines.h; sourceTree = "<group>"; };
                0F7C39FC1C8F659500480151 /* RegExpObjectInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpObjectInlines.h; sourceTree = "<group>"; };
                0F7C39FE1C90C55B00480151 /* DFGOpInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOpInfo.h; path = dfg/DFGOpInfo.h; sourceTree = "<group>"; };
                796FB4391DFF8C3F0039C95D /* JSWebAssemblyHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSWebAssemblyHelpers.h; path = js/JSWebAssemblyHelpers.h; sourceTree = "<group>"; };
                797E07A71B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalLexicalEnvironment.cpp; sourceTree = "<group>"; };
                797E07A81B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalLexicalEnvironment.h; sourceTree = "<group>"; };
+               7980C16A1E3A940E00B71615 /* DFGRegisteredStructureSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGRegisteredStructureSet.cpp; path = dfg/DFGRegisteredStructureSet.cpp; sourceTree = "<group>"; };
+               7980C16B1E3A940E00B71615 /* DFGRegisteredStructureSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGRegisteredStructureSet.h; path = dfg/DFGRegisteredStructureSet.h; sourceTree = "<group>"; };
                798937761DCAB57300F8D4FB /* JSFixedArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFixedArray.cpp; sourceTree = "<group>"; };
                798937771DCAB57300F8D4FB /* JSFixedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSFixedArray.h; sourceTree = "<group>"; };
                799EF7C31C56ED96002B0534 /* B3PCToOriginMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3PCToOriginMap.h; path = b3/B3PCToOriginMap.h; sourceTree = "<group>"; };
                79EE0BFE1B4AFB85000385C9 /* VariableEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VariableEnvironment.h; sourceTree = "<group>"; };
                79F8FC1C1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGMaximalFlushInsertionPhase.cpp; path = dfg/DFGMaximalFlushInsertionPhase.cpp; sourceTree = "<group>"; };
                79F8FC1D1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGMaximalFlushInsertionPhase.h; path = dfg/DFGMaximalFlushInsertionPhase.h; sourceTree = "<group>"; };
+               79FC8A071E32E9F000D88F0E /* DFGRegisteredStructure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGRegisteredStructure.h; path = dfg/DFGRegisteredStructure.h; sourceTree = "<group>"; };
                7BC547D21B69599B00959B58 /* WasmFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmFormat.h; sourceTree = "<group>"; };
                7C008CD8187124BB00955C24 /* JSPromiseDeferred.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPromiseDeferred.cpp; sourceTree = "<group>"; };
                7C008CD9187124BB00955C24 /* JSPromiseDeferred.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPromiseDeferred.h; sourceTree = "<group>"; };
                                0FB1765F196B8F9E0091052A /* DFGPureValue.h */,
                                0F3A1BF71A9ECB7D000DE01A /* DFGPutStackSinkingPhase.cpp */,
                                0F3A1BF81A9ECB7D000DE01A /* DFGPutStackSinkingPhase.h */,
+                               79FC8A071E32E9F000D88F0E /* DFGRegisteredStructure.h */,
+                               7980C16A1E3A940E00B71615 /* DFGRegisteredStructureSet.cpp */,
+                               7980C16B1E3A940E00B71615 /* DFGRegisteredStructureSet.h */,
                                86EC9DC11328DF82002B2AD7 /* DFGRegisterBank.h */,
                                0F2FCCF418A60070001A27F8 /* DFGSafepoint.cpp */,
                                0F2FCCF518A60070001A27F8 /* DFGSafepoint.h */,
                                0F893BDA1936E23C001211F4 /* DFGStructureAbstractValue.cpp */,
                                0F63947615DCE347006A597C /* DFGStructureAbstractValue.h */,
                                0F50AF3B193E8B3900674EE8 /* DFGStructureClobberState.h */,
-                               0F79085319A290B200F6310C /* DFGStructureRegistrationPhase.cpp */,
-                               0F79085419A290B200F6310C /* DFGStructureRegistrationPhase.h */,
                                0F2FCCF718A60070001A27F8 /* DFGThreadData.cpp */,
                                0F2FCCF818A60070001A27F8 /* DFGThreadData.h */,
                                0FC0979F146B28C700CF2442 /* DFGThunks.cpp */,
                                0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
                                0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
                                0FA762051DB9242900B7A2FD /* CollectionScope.h in Headers */,
+                               79FC8A081E32E9F000D88F0E /* DFGRegisteredStructure.h in Headers */,
                                A53243981856A489002ED692 /* CombinedDomains.json in Headers */,
                                BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
                                0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */,
                                0FC20CB61852E2C600C9E954 /* DFGStrengthReductionPhase.h in Headers */,
                                0F63947815DCE34B006A597C /* DFGStructureAbstractValue.h in Headers */,
                                0F50AF3C193E8B3900674EE8 /* DFGStructureClobberState.h in Headers */,
-                               0F79085619A290B200F6310C /* DFGStructureRegistrationPhase.h in Headers */,
                                0F2FCCFF18A60070001A27F8 /* DFGThreadData.h in Headers */,
                                0FC097A2146B28CC00CF2442 /* DFGThunks.h in Headers */,
                                0FD8A32817D51F5700CA2C40 /* DFGTierUpCheckInjectionPhase.h in Headers */,
                                A50E4B6418809DD50068A46D /* JSGlobalObjectRuntimeAgent.h in Headers */,
                                A503FA2A188F105900110F14 /* JSGlobalObjectScriptDebugServer.h in Headers */,
                                A513E5C0185BFACC007E95AD /* JSInjectedScriptHost.h in Headers */,
+                               7980C16D1E3A940E00B71615 /* DFGRegisteredStructureSet.h in Headers */,
                                A513E5C2185BFACC007E95AD /* JSInjectedScriptHostPrototype.h in Headers */,
                                C442CB251A6CDB8C005D3D7C /* JSInputs.json in Headers */,
                                0F2B66F817B6B5AB00A7AE3F /* JSInt16Array.h in Headers */,
                                0FC20CB51852E2C600C9E954 /* DFGStrengthReductionPhase.cpp in Sources */,
                                0F7DF13B1E2971110095951B /* JSDestructibleObjectSubspace.cpp in Sources */,
                                0F893BDB1936E23C001211F4 /* DFGStructureAbstractValue.cpp in Sources */,
-                               0F79085519A290B200F6310C /* DFGStructureRegistrationPhase.cpp in Sources */,
                                0F2FCCFE18A60070001A27F8 /* DFGThreadData.cpp in Sources */,
                                0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */,
                                0FD8A32717D51F5700CA2C40 /* DFGTierUpCheckInjectionPhase.cpp in Sources */,
                                14AD91171DCA97FD0014F9FE /* EvalCodeBlock.cpp in Sources */,
                                147341E21DC2CE9600AA29BA /* EvalExecutable.cpp in Sources */,
                                A54982031891D0B00081E5B8 /* EventLoop.cpp in Sources */,
+                               7980C16C1E3A940E00B71615 /* DFGRegisteredStructureSet.cpp in Sources */,
                                FE1C0FFF1B194FD100B53FCA /* Exception.cpp in Sources */,
                                FE80C19B1D776A98008510C0 /* ExceptionEventLocation.cpp in Sources */,
                                0F12DE0F1979D5FD0006FF4E /* ExceptionFuzz.cpp in Sources */,
index 79a12c2..1cc783c 100644 (file)
@@ -2725,6 +2725,7 @@ void CodeBlock::determineLiveness(const ConcurrentJSLocker&, SlotVisitor& visito
     // GC we still have not proved liveness, then this code block is toast.
     bool allAreLiveSoFar = true;
     for (unsigned i = 0; i < dfgCommon->weakReferences.size(); ++i) {
+        ASSERT(!jsDynamicCast<CodeBlock*>(dfgCommon->weakReferences[i].get()));
         if (!Heap::isMarkedConcurrently(dfgCommon->weakReferences[i].get())) {
             allAreLiveSoFar = false;
             break;
index 40fea8d..2ccb8f0 100644 (file)
 #include "config.h"
 #include "StructureSet.h"
 
-#include "DFGAbstractValue.h"
 #include "TrackedReferences.h"
 #include <wtf/CommaPrinter.h>
 
 namespace JSC {
 
-#if ENABLE(DFG_JIT)
-
-void StructureSet::filter(const DFG::StructureAbstractValue& other)
-{
-    genericFilter([&] (Structure* structure) -> bool { return other.contains(structure); });
-}
-
-void StructureSet::filter(SpeculatedType type)
-{
-    genericFilter(
-        [&] (Structure* structure) -> bool {
-            return type & speculationFromStructure(structure);
-        });
-}
-
-void StructureSet::filterArrayModes(ArrayModes arrayModes)
-{
-    genericFilter(
-        [&] (Structure* structure) -> bool {
-            return arrayModes & arrayModeFromStructure(structure);
-        });
-}
-
-void StructureSet::filter(const DFG::AbstractValue& other)
-{
-    filter(other.m_structure);
-    filter(other.m_type);
-    filterArrayModes(other.m_arrayModes);
-}
-
-#endif // ENABLE(DFG_JIT)
-
-SpeculatedType StructureSet::speculationFromStructures() const
-{
-    SpeculatedType result = SpecNone;
-    forEach(
-        [&] (Structure* structure) {
-            mergeSpeculation(result, speculationFromStructure(structure));
-        });
-    return result;
-}
-
-ArrayModes StructureSet::arrayModesFromStructures() const
-{
-    ArrayModes result = 0;
-    forEach(
-        [&] (Structure* structure) {
-            mergeArrayModes(result, asArrayModes(structure->indexingType()));
-        });
-    return result;
-}
-
 void StructureSet::dumpInContext(PrintStream& out, DumpContext* context) const
 {
     CommaPrinter comma;
@@ -97,13 +44,5 @@ void StructureSet::dump(PrintStream& out) const
     dumpInContext(out, nullptr);
 }
 
-void StructureSet::validateReferences(const TrackedReferences& trackedReferences) const
-{
-    forEach(
-        [&] (Structure* structure) {
-            trackedReferences.check(structure);
-        });
-}
-
 } // namespace JSC
 
index 5963489..8654ca5 100644 (file)
@@ -35,11 +35,6 @@ namespace JSC {
 
 class TrackedReferences;
 
-namespace DFG {
-class StructureAbstractValue;
-struct AbstractValue;
-}
-
 class StructureSet : public TinyPtrSet<Structure*> {
 public:
     // I really want to do this:
@@ -66,20 +61,8 @@ public:
         return onlyEntry();
     }
     
-#if ENABLE(DFG_JIT)
-    void filter(const DFG::StructureAbstractValue&);
-    void filter(SpeculatedType);
-    void filterArrayModes(ArrayModes);
-    void filter(const DFG::AbstractValue&);
-#endif // ENABLE(DFG_JIT)
-    
-    SpeculatedType speculationFromStructures() const;
-    ArrayModes arrayModesFromStructures() const;
-    
     void dumpInContext(PrintStream&, DumpContext*) const;
     void dump(PrintStream&) const;
-    
-    void validateReferences(const TrackedReferences&) const;
 };
 
 } // namespace JSC
index af5f33e..4c01471 100644 (file)
@@ -112,7 +112,7 @@ public:
     void dump(PrintStream& out);
     
     template<typename T>
-    FiltrationResult filter(T node, const StructureSet& set, SpeculatedType admittedTypes = SpecNone)
+    FiltrationResult filter(T node, const RegisteredStructureSet& set, SpeculatedType admittedTypes = SpecNone)
     {
         return filter(forNode(node), set, admittedTypes);
     }
@@ -141,7 +141,7 @@ public:
         return filterClassInfo(forNode(node), classInfo);
     }
 
-    FiltrationResult filter(AbstractValue&, const StructureSet&, SpeculatedType admittedTypes = SpecNone);
+    FiltrationResult filter(AbstractValue&, const RegisteredStructureSet&, SpeculatedType admittedTypes = SpecNone);
     FiltrationResult filterArrayModes(AbstractValue&, ArrayModes);
     FiltrationResult filter(AbstractValue&, SpeculatedType);
     FiltrationResult filterByValue(AbstractValue&, FrozenValue);
@@ -156,7 +156,7 @@ private:
     void forAllValues(unsigned indexInBlock, Functor&);
     
     void clobberStructures(unsigned indexInBlock);
-    void observeTransition(unsigned indexInBlock, Structure* from, Structure* to);
+    void observeTransition(unsigned indexInBlock, RegisteredStructure from, RegisteredStructure to);
     void observeTransitions(unsigned indexInBlock, const TransitionVector&);
     void setDidClobber();
     
index ad8ec4a..dfd268f 100644 (file)
@@ -73,7 +73,7 @@ AbstractInterpreter<AbstractStateType>::booleanResult(
     if (isCellSpeculation(value.m_type) && !value.m_structure.isTop()) {
         bool allTrue = true;
         for (unsigned i = value.m_structure.size(); i--;) {
-            Structure* structure = value.m_structure[i];
+            RegisteredStructure structure = value.m_structure[i];
             if (structure->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
                 || structure->typeInfo().type() == StringType) {
                 allTrue = false;
@@ -152,7 +152,7 @@ inline bool isToThisAnIdentity(bool isStrictMode, AbstractValue& valueForNode)
 
     if ((isStrictMode || (valueForNode.m_type && !(valueForNode.m_type & ~SpecObject))) && valueForNode.m_structure.isFinite()) {
         bool overridesToThis = false;
-        valueForNode.m_structure.forEach([&](Structure* structure) {
+        valueForNode.m_structure.forEach([&](RegisteredStructure structure) {
             TypeInfo type = structure->typeInfo();
             ASSERT(type.isObject() || type.type() == StringType || type.type() == SymbolType);
             if (!isStrictMode)
@@ -1656,10 +1656,10 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
 
         // FIXME: We could do better here if we prove that the
         // incoming value has only a single structure.
-        StructureSet structureSet;
-        structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithInt32));
-        structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous));
-        structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithDouble));
+        RegisteredStructureSet structureSet;
+        structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithInt32)));
+        structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous)));
+        structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithDouble)));
 
         forNode(node).set(m_graph, structureSet);
         break;
@@ -1856,7 +1856,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             // structure.
             filter(
                 node->child1(),
-                m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure());
+                m_graph.registerStructure(m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure()));
             break;
         case StringOrStringObjectUse:
             break;
@@ -1963,7 +1963,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     }
         
     case NewObject:
-        ASSERT(node->structure());
+        ASSERT(!!node->structure().get());
         forNode(node).set(m_graph, node->structure());
         break;
 
@@ -2121,7 +2121,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             JSGlobalObject* globalObject = nullptr;
             bool ok = true;
             forNode(node->child1()).m_structure.forEach(
-                [&] (Structure* structure) {
+                [&] (RegisteredStructure structure) {
                     if (!globalObject)
                         globalObject = structure->globalObject();
                     else if (globalObject != structure->globalObject())
@@ -2184,7 +2184,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         if (value.m_structure.isFinite()
             && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
             UniquedStringImpl* uid = m_graph.identifiers()[node->identifierNumber()];
-            GetByIdStatus status = GetByIdStatus::computeFor(value.m_structure.set(), uid);
+            GetByIdStatus status = GetByIdStatus::computeFor(value.m_structure.toStructureSet(), uid);
             if (status.isSimple()) {
                 // Figure out what the result is going to be - is it TOP, a constant, or maybe
                 // something more subtle?
@@ -2238,7 +2238,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case CheckStructure: {
         AbstractValue& value = forNode(node->child1());
 
-        StructureSet& set = node->structureSet();
+        const RegisteredStructureSet& set = node->structureSet();
         
         // It's interesting that we could have proven that the object has a larger structure set
         // that includes the set we're testing. In that case we could make the structure check
@@ -2270,11 +2270,11 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         // https://bugs.webkit.org/show_bug.cgi?id=136988
         
         AbstractValue& value = forNode(node->child1());
-        StructureSet& set = node->structureSet();
+        const RegisteredStructureSet& set = node->structureSet();
         
         if (value.value()) {
             if (Structure* structure = jsDynamicCast<Structure*>(value.value())) {
-                if (set.contains(structure)) {
+                if (set.contains(m_graph.registerStructure(structure))) {
                     m_state.setFoundConstants(true);
                     break;
                 }
@@ -2289,7 +2289,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 node,
                 [&] (Node* incoming) {
                     if (Structure* structure = incoming->dynamicCastConstant<Structure*>()) {
-                        if (set.contains(structure))
+                        if (set.contains(m_graph.registerStructure(structure)))
                             return;
                     }
                     allGood = false;
@@ -2300,8 +2300,8 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             }
         }
             
-        if (Structure* structure = set.onlyStructure()) {
-            filterByValue(node->child1(), *m_graph.freeze(structure));
+        if (RegisteredStructure structure = set.onlyStructure()) {
+            filterByValue(node->child1(), *m_graph.freeze(structure.get()));
             break;
         }
         
@@ -2432,7 +2432,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     }
     case ArrayifyToStructure: {
         AbstractValue& value = forNode(node->child1());
-        if (value.m_structure.isSubsetOf(StructureSet(node->structure())))
+        if (value.m_structure.isSubsetOf(RegisteredStructureSet(node->structure())))
             m_state.setFoundConstants(true);
         clobberStructures(clobberLimit);
         
@@ -2546,10 +2546,10 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         UniquedStringImpl* uid = m_graph.identifiers()[node->multiGetByOffsetData().identifierNumber];
 
         AbstractValue base = forNode(node->child1());
-        StructureSet baseSet;
+        RegisteredStructureSet baseSet;
         AbstractValue result;
         for (const MultiGetByOffsetCase& getCase : node->multiGetByOffsetData().cases) {
-            StructureSet set = getCase.set();
+            RegisteredStructureSet set = getCase.set();
             set.filter(base);
             if (set.isEmpty())
                 continue;
@@ -2591,7 +2591,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     }
         
     case MultiPutByOffset: {
-        StructureSet newSet;
+        RegisteredStructureSet newSet;
         TransitionVector transitions;
         
         // Ordinarily you have to be careful with calling setFoundConstants()
@@ -2604,7 +2604,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         
         for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
             const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
-            StructureSet thisSet = variant.oldStructure();
+            RegisteredStructureSet thisSet = *m_graph.addStructureSet(variant.oldStructure());
             thisSet.filter(base);
             if (thisSet.isEmpty())
                 continue;
@@ -2614,11 +2614,12 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             resultingValue.merge(thisValue);
             
             if (variant.kind() == PutByIdVariant::Transition) {
-                if (thisSet.onlyStructure() != variant.newStructure()) {
+                RegisteredStructure newStructure = m_graph.registerStructure(variant.newStructure());
+                if (thisSet.onlyStructure() != newStructure) {
                     transitions.append(
-                        Transition(variant.oldStructureForTransition(), variant.newStructure()));
+                        Transition(m_graph.registerStructure(variant.oldStructureForTransition()), newStructure));
                 } // else this is really a replace.
-                newSet.add(variant.newStructure());
+                newSet.add(newStructure);
             } else {
                 ASSERT(variant.kind() == PutByIdVariant::Replace);
                 newSet.merge(thisSet);
@@ -2705,25 +2706,25 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         if (value.m_structure.isFinite()) {
             PutByIdStatus status = PutByIdStatus::computeFor(
                 m_graph.globalObjectFor(node->origin.semantic),
-                value.m_structure.set(),
+                value.m_structure.toStructureSet(),
                 m_graph.identifiers()[node->identifierNumber()],
                 node->op() == PutByIdDirect);
 
             if (status.isSimple()) {
-                StructureSet newSet;
+                RegisteredStructureSet newSet;
                 TransitionVector transitions;
                 
                 for (unsigned i = status.numVariants(); i--;) {
                     const PutByIdVariant& variant = status[i];
                     if (variant.kind() == PutByIdVariant::Transition) {
+                        RegisteredStructure newStructure = m_graph.registerStructure(variant.newStructure());
                         transitions.append(
                             Transition(
-                                variant.oldStructureForTransition(), variant.newStructure()));
-                        m_graph.registerStructure(variant.newStructure());
-                        newSet.add(variant.newStructure());
+                                m_graph.registerStructure(variant.oldStructureForTransition()), newStructure));
+                        newSet.add(newStructure);
                     } else {
                         ASSERT(variant.kind() == PutByIdVariant::Replace);
-                        newSet.merge(variant.oldStructure());
+                        newSet.merge(*m_graph.addStructureSet(variant.oldStructure()));
                     }
                 }
                 
@@ -3059,7 +3060,7 @@ void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned clobberL
 
 template<typename AbstractStateType>
 void AbstractInterpreter<AbstractStateType>::observeTransition(
-    unsigned clobberLimit, Structure* from, Structure* to)
+    unsigned clobberLimit, RegisteredStructure from, RegisteredStructure to)
 {
     AbstractValue::TransitionObserver transitionObserver(from, to);
     forAllValues(clobberLimit, transitionObserver);
@@ -3132,7 +3133,7 @@ void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out)
 
 template<typename AbstractStateType>
 FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
-    AbstractValue& value, const StructureSet& set, SpeculatedType admittedTypes)
+    AbstractValue& value, const RegisteredStructureSet& set, SpeculatedType admittedTypes)
 {
     if (value.filter(m_graph, set, admittedTypes) == FiltrationOK)
         return FiltrationOK;
index b287c27..4a7fe1b 100644 (file)
@@ -52,8 +52,10 @@ void AbstractValue::set(Graph& graph, const FrozenValue& value, StructureClobber
 {
     if (!!value && value.value().isCell()) {
         Structure* structure = value.structure();
-        if (graph.registerStructure(structure) == StructureRegisteredAndWatched) {
-            m_structure = structure;
+        StructureRegistrationResult result;
+        RegisteredStructure RegisteredStructure = graph.registerStructure(structure, result);
+        if (result == StructureRegisteredAndWatched) {
+            m_structure = RegisteredStructure;
             if (clobberState == StructuresAreClobbered) {
                 m_arrayModes = ALL_ARRAY_MODES;
                 m_structure.clobber();
@@ -77,18 +79,23 @@ void AbstractValue::set(Graph& graph, const FrozenValue& value, StructureClobber
 
 void AbstractValue::set(Graph& graph, Structure* structure)
 {
+    set(graph, graph.registerStructure(structure));
+}
+
+void AbstractValue::set(Graph& graph, RegisteredStructure structure)
+{
     RELEASE_ASSERT(structure);
     
     m_structure = structure;
     m_arrayModes = asArrayModes(structure->indexingType());
-    m_type = speculationFromStructure(structure);
+    m_type = speculationFromStructure(structure.get());
     m_value = JSValue();
     
     checkConsistency();
     assertIsRegistered(graph);
 }
 
-void AbstractValue::set(Graph& graph, const StructureSet& set)
+void AbstractValue::set(Graph& graph, const RegisteredStructureSet& set)
 {
     m_structure = set;
     m_arrayModes = set.arrayModesFromStructures();
@@ -104,9 +111,9 @@ void AbstractValue::setType(Graph& graph, SpeculatedType type)
     SpeculatedType cellType = type & SpecCell;
     if (cellType) {
         if (!(cellType & ~SpecString))
-            m_structure = graph.m_vm.stringStructure.get();
+            m_structure = graph.stringStructure;
         else if (isSymbolSpeculation(cellType))
-            m_structure = graph.m_vm.symbolStructure.get();
+            m_structure = graph.symbolStructure;
         else
             m_structure.makeTop();
         m_arrayModes = ALL_ARRAY_MODES;
@@ -217,7 +224,7 @@ bool AbstractValue::mergeOSREntryValue(Graph& graph, JSValue value)
     if (isClear()) {
         FrozenValue* frozenValue = graph.freeze(value);
         if (frozenValue->pointsToHeap()) {
-            m_structure = frozenValue->structure();
+            m_structure = graph.registerStructure(frozenValue->structure());
             m_arrayModes = asArrayModes(frozenValue->structure()->indexingType());
         } else {
             m_structure.clear();
@@ -229,10 +236,9 @@ bool AbstractValue::mergeOSREntryValue(Graph& graph, JSValue value)
     } else {
         mergeSpeculation(m_type, speculationFromValue(value));
         if (!!value && value.isCell()) {
-            Structure* structure = value.asCell()->structure();
-            graph.registerStructure(structure);
+            RegisteredStructure structure = graph.registerStructure(value.asCell()->structure());
             mergeArrayModes(m_arrayModes, asArrayModes(structure->indexingType()));
-            m_structure.merge(StructureSet(structure));
+            m_structure.merge(RegisteredStructureSet(structure));
         }
         if (m_value != value)
             m_value = JSValue();
@@ -256,7 +262,7 @@ bool AbstractValue::isType(Graph& graph, const InferredType::Descriptor& inferre
 }
 
 FiltrationResult AbstractValue::filter(
-    Graph& graph, const StructureSet& other, SpeculatedType admittedTypes)
+    Graph& graph, const RegisteredStructureSet& other, SpeculatedType admittedTypes)
 {
     ASSERT(!(admittedTypes & SpecCell));
     
@@ -272,10 +278,10 @@ FiltrationResult AbstractValue::filter(
     m_structure.filter(other);
     
     // It's possible that prior to the above two statements we had (Foo, TOP), where
-    // Foo is a SpeculatedType that is disjoint with the passed StructureSet. In that
+    // Foo is a SpeculatedType that is disjoint with the passed RegisteredStructureSet. In that
     // case, we will now have (None, [someStructure]). In general, we need to make
     // sure that new information gleaned from the SpeculatedType needs to be fed back
-    // into the information gleaned from the StructureSet.
+    // into the information gleaned from the RegisteredStructureSet.
     m_structure.filter(m_type);
     
     filterArrayModesByType();
@@ -283,7 +289,7 @@ FiltrationResult AbstractValue::filter(
     return normalizeClarity(graph);
 }
 
-FiltrationResult AbstractValue::changeStructure(Graph& graph, const StructureSet& other)
+FiltrationResult AbstractValue::changeStructure(Graph& graph, const RegisteredStructureSet& other)
 {
     m_type &= other.speculationFromStructures();
     m_arrayModes = other.arrayModesFromStructures();
@@ -361,10 +367,10 @@ FiltrationResult AbstractValue::filterByValue(const FrozenValue& value)
     return result;
 }
 
-bool AbstractValue::contains(Structure* structure) const
+bool AbstractValue::contains(RegisteredStructure structure) const
 {
-    return couldBeType(speculationFromStructure(structure))
-        && (m_arrayModes & arrayModeFromStructure(structure))
+    return couldBeType(speculationFromStructure(structure.get()))
+        && (m_arrayModes & arrayModeFromStructure(structure.get()))
         && m_structure.contains(structure);
 }
 
index 8a91014..03a5056 100644 (file)
@@ -38,7 +38,6 @@
 #include "ResultType.h"
 #include "SpeculatedType.h"
 #include "DumpContext.h"
-#include "StructureSet.h"
 
 namespace JSC {
 
@@ -120,7 +119,7 @@ struct AbstractValue {
         value.observeInvalidationPoint();
     }
     
-    void observeTransition(Structure* from, Structure* to)
+    void observeTransition(RegisteredStructure from, RegisteredStructure to)
     {
         if (m_type & SpecCell) {
             m_structure.observeTransition(from, to);
@@ -133,7 +132,7 @@ struct AbstractValue {
     
     class TransitionObserver {
     public:
-        TransitionObserver(Structure* from, Structure* to)
+        TransitionObserver(RegisteredStructure from, RegisteredStructure to)
             : m_from(from)
             , m_to(to)
         {
@@ -144,8 +143,8 @@ struct AbstractValue {
             value.observeTransition(m_from, m_to);
         }
     private:
-        Structure* m_from;
-        Structure* m_to;
+        RegisteredStructure m_from;
+        RegisteredStructure m_to;
     };
     
     class TransitionsObserver {
@@ -209,7 +208,8 @@ struct AbstractValue {
     
     void set(Graph&, const FrozenValue&, StructureClobberState);
     void set(Graph&, Structure*);
-    void set(Graph&, const StructureSet&);
+    void set(Graph&, RegisteredStructure);
+    void set(Graph&, const RegisteredStructureSet&);
     
     // Set this value to represent the given set of types as precisely as possible.
     void setType(Graph&, SpeculatedType);
@@ -301,7 +301,7 @@ struct AbstractValue {
     // 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&, const StructureSet&, SpeculatedType admittedTypes = SpecNone);
+    FiltrationResult filter(Graph&, const RegisteredStructureSet&, SpeculatedType admittedTypes = SpecNone);
     
     FiltrationResult filterArrayModes(ArrayModes);
     FiltrationResult filter(SpeculatedType);
@@ -311,9 +311,9 @@ struct AbstractValue {
 
     FiltrationResult filter(Graph&, const InferredType::Descriptor&);
     
-    FiltrationResult changeStructure(Graph&, const StructureSet&);
+    FiltrationResult changeStructure(Graph&, const RegisteredStructureSet&);
     
-    bool contains(Structure*) const;
+    bool contains(RegisteredStructure) const;
 
     bool validate(JSValue value) const
     {
index 884fd84..b93be30 100644 (file)
@@ -393,7 +393,7 @@ private:
                     }
                     ASSERT(structure);
 
-                    if (!node->structureSet().contains(structure))
+                    if (!node->structureSet().contains(m_graph.registerStructure(structure)))
                         escape(node->child1(), node);
                     break;
                 }
index 7778bb3..a26530e 100644 (file)
@@ -360,12 +360,12 @@ bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& va
         if (value.m_structure.isTop())
             return false;
         for (unsigned i = value.m_structure.size(); i--;) {
-            Structure* structure = value.m_structure[i];
+            RegisteredStructure structure = value.m_structure[i];
             if ((structure->indexingType() & IndexingShapeMask) != shape)
                 return false;
             if (!(structure->indexingType() & IsArray))
                 return false;
-            if (!graph.globalObjectFor(node->origin.semantic)->isOriginalArrayStructure(structure))
+            if (!graph.globalObjectFor(node->origin.semantic)->isOriginalArrayStructure(structure.get()))
                 return false;
         }
         return true;
@@ -377,7 +377,7 @@ bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& va
         if (value.m_structure.isTop())
             return false;
         for (unsigned i = value.m_structure.size(); i--;) {
-            Structure* structure = value.m_structure[i];
+            RegisteredStructure structure = value.m_structure[i];
             if ((structure->indexingType() & IndexingShapeMask) != shape)
                 return false;
             if (!(structure->indexingType() & IsArray))
@@ -392,7 +392,7 @@ bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& va
         if (value.m_structure.isTop())
             return false;
         for (unsigned i = value.m_structure.size(); i--;) {
-            Structure* structure = value.m_structure[i];
+            RegisteredStructure structure = value.m_structure[i];
             if ((structure->indexingType() & IndexingShapeMask) != shape)
                 return false;
         }
@@ -440,7 +440,7 @@ bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& va
             if (value.m_structure.isTop())
                 return false;
             for (unsigned i = value.m_structure.size(); i--;) {
-                Structure* structure = value.m_structure[i];
+                RegisteredStructure structure = value.m_structure[i];
                 if (!hasAnyArrayStorage(structure->indexingType()))
                     return false;
                 if (!(structure->indexingType() & IsArray))
@@ -455,7 +455,7 @@ bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& va
             if (value.m_structure.isTop())
                 return false;
             for (unsigned i = value.m_structure.size(); i--;) {
-                Structure* structure = value.m_structure[i];
+                RegisteredStructure structure = value.m_structure[i];
                 if (!hasAnyArrayStorage(structure->indexingType()))
                     return false;
             }
index a33da6e..ba4d5fe 100644 (file)
@@ -45,7 +45,7 @@ public:
         : JumpingSlowPathGenerator<MacroAssembler::JumpList>(from, jit)
         , m_op(node->op())
         , m_arrayMode(node->arrayMode())
-        , m_structure(node->op() == ArrayifyToStructure ? node->structure() : 0)
+        , m_structure(node->op() == ArrayifyToStructure ? node->structure() : RegisteredStructure())
         , m_baseGPR(baseGPR)
         , m_propertyGPR(propertyGPR)
         , m_tempGPR(tempGPR)
@@ -115,7 +115,7 @@ protected:
         jit->m_jit.exceptionCheck();
         
         if (m_op == ArrayifyToStructure) {
-            ASSERT(m_structure);
+            ASSERT(m_structure.get());
             m_badIndexingTypeJump.fill(
                 jit, jit->m_jit.branchWeakStructure(MacroAssembler::NotEqual, MacroAssembler::Address(m_baseGPR, JSCell::structureIDOffset()), m_structure));
         } else {
@@ -136,7 +136,7 @@ protected:
 private:
     NodeType m_op;
     ArrayMode m_arrayMode;
-    Structure* m_structure;
+    RegisteredStructure m_structure;
     GPRReg m_baseGPR;
     GPRReg m_propertyGPR;
     GPRReg m_tempGPR;
index 0ac3250..353c096 100644 (file)
@@ -2960,7 +2960,7 @@ bool ByteCodeParser::handleConstantInternalFunction(
             result = addToGraph(CallStringConstructor, get(virtualRegisterForArgument(1, registerOffset)));
         
         if (kind == CodeForConstruct)
-            result = addToGraph(NewStringObject, OpInfo(function->globalObject()->stringObjectStructure()), result);
+            result = addToGraph(NewStringObject, OpInfo(m_graph.registerStructure(function->globalObject()->stringObjectStructure())), result);
         
         set(VirtualRegister(resultOperand), result);
         return true;
@@ -2972,7 +2972,7 @@ bool ByteCodeParser::handleConstantInternalFunction(
 
         Node* result;
         if (argumentCountIncludingThis <= 1)
-            result = addToGraph(NewObject, OpInfo(function->globalObject()->objectStructureForObjectConstructor()));
+            result = addToGraph(NewObject, OpInfo(m_graph.registerStructure(function->globalObject()->objectStructureForObjectConstructor())));
         else
             result = addToGraph(CallObjectConstructor, get(virtualRegisterForArgument(1, registerOffset)));
         set(VirtualRegister(resultOperand), result);
@@ -3383,7 +3383,7 @@ Node* ByteCodeParser::load(
             // We did emit a structure check. That means that we have an opportunity to do constant folding
             // here, since we didn't do it above.
             JSValue constant = m_graph.tryGetConstantProperty(
-                base->asJSValue(), variant.structureSet(), variant.offset());
+                base->asJSValue(), *m_graph.addStructureSet(variant.structureSet()), variant.offset());
             if (constant)
                 return weakJSConstant(constant);
         }
@@ -3429,7 +3429,7 @@ void ByteCodeParser::handleGetById(
             }
         }
         if (ok)
-            getByIdStatus.filter(base->structure());
+            getByIdStatus.filter(base->structure().get());
     }
     
     NodeType getById;
@@ -3482,7 +3482,7 @@ void ByteCodeParser::handleGetById(
             if (variant.conditionSet().isEmpty()) {
                 cases.append(
                     MultiGetByOffsetCase(
-                        variant.structureSet(),
+                        *m_graph.addStructureSet(variant.structureSet()),
                         GetByOffsetMethod::load(variant.offset())));
                 continue;
             }
@@ -3494,7 +3494,7 @@ void ByteCodeParser::handleGetById(
                 return;
             }
             
-            cases.append(MultiGetByOffsetCase(variant.structureSet(), method));
+            cases.append(MultiGetByOffsetCase(*m_graph.addStructureSet(variant.structureSet()), method));
         }
 
         if (m_graph.compilation())
@@ -3621,8 +3621,13 @@ void ByteCodeParser::handlePutById(
         if (m_graph.compilation())
             m_graph.compilation()->noticeInlinedPutById();
 
-        for (const PutByIdVariant& variant : putByIdStatus.variants())
+        for (const PutByIdVariant& variant : putByIdStatus.variants()) {
             m_graph.registerInferredType(variant.requiredType());
+            for (Structure* structure : variant.oldStructure())
+                m_graph.registerStructure(structure);
+            if (variant.kind() == PutByIdVariant::Transition)
+                m_graph.registerStructure(variant.newStructure());
+        }
         
         MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add();
         data->variants = putByIdStatus.variants();
@@ -3653,7 +3658,7 @@ void ByteCodeParser::handlePutById(
     
         Node* propertyStorage;
         Transition* transition = m_graph.m_transitions.add(
-            variant.oldStructureForTransition(), variant.newStructure());
+            m_graph.registerStructure(variant.oldStructureForTransition()), m_graph.registerStructure(variant.newStructure()));
 
         if (variant.reallocatesStorage()) {
 
@@ -3900,7 +3905,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                         m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
                         // The callee is still live up to this point.
                         addToGraph(Phantom, callee);
-                        set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(NewObject, OpInfo(structure)));
+                        set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(NewObject, OpInfo(m_graph.registerStructure(structure))));
                         alreadyEmitted = true;
                     }
                 }
@@ -3915,7 +3920,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         case op_new_object: {
             set(VirtualRegister(currentInstruction[1].u.operand),
                 addToGraph(NewObject,
-                    OpInfo(currentInstruction[3].u.objectAllocationProfile->structure())));
+                    OpInfo(m_graph.registerStructure(currentInstruction[3].u.objectAllocationProfile->structure()))));
             NEXT_OPCODE(op_new_object);
         }
             
@@ -5678,7 +5683,7 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
         ASSERT(callsiteBlockHead);
         
         m_inlineCallFrame = byteCodeParser->m_graph.m_plan.inlineCallFrames->add();
-        byteCodeParser->m_graph.freeze(codeBlock->baselineVersion());
+
         // The owner is the machine code block, and we already have a barrier on that when the
         // plan finishes.
         m_inlineCallFrame->baselineCodeBlock.setWithoutWriteBarrier(codeBlock->baselineVersion());
index 53dad50..59c4092 100644 (file)
@@ -38,7 +38,7 @@ class CallArrayAllocatorSlowPathGenerator : public JumpingSlowPathGenerator<Macr
 public:
     CallArrayAllocatorSlowPathGenerator(
         MacroAssembler::JumpList from, SpeculativeJIT* jit, P_JITOperation_EStZB function,
-        GPRReg resultGPR, GPRReg storageGPR, Structure* structure, size_t size)
+        GPRReg resultGPR, GPRReg storageGPR, RegisteredStructure structure, size_t size)
         : JumpingSlowPathGenerator<MacroAssembler::JumpList>(from, jit)
         , m_function(function)
         , m_resultGPR(resultGPR)
@@ -69,7 +69,7 @@ private:
     P_JITOperation_EStZB m_function;
     GPRReg m_resultGPR;
     GPRReg m_storageGPR;
-    Structure* m_structure;
+    RegisteredStructure m_structure;
     size_t m_size;
     Vector<SilentRegisterSavePlan, 2> m_plans;
 };
@@ -78,7 +78,7 @@ class CallArrayAllocatorWithVariableSizeSlowPathGenerator : public JumpingSlowPa
 public:
     CallArrayAllocatorWithVariableSizeSlowPathGenerator(
         MacroAssembler::JumpList from, SpeculativeJIT* jit, P_JITOperation_EStZB function,
-        GPRReg resultGPR, Structure* contiguousStructure, Structure* arrayStorageStructure, GPRReg sizeGPR, GPRReg storageGPR)
+        GPRReg resultGPR, RegisteredStructure contiguousStructure, RegisteredStructure arrayStorageStructure, GPRReg sizeGPR, GPRReg storageGPR)
         : JumpingSlowPathGenerator<MacroAssembler::JumpList>(from, jit)
         , m_function(function)
         , m_resultGPR(resultGPR)
@@ -97,15 +97,15 @@ protected:
         for (unsigned i = 0; i < m_plans.size(); ++i)
             jit->silentSpill(m_plans[i]);
         GPRReg scratchGPR = AssemblyHelpers::selectScratchGPR(m_sizeGPR, m_storageGPR);
-        if (m_contiguousStructure != m_arrayStorageOrContiguousStructure) {
+        if (m_contiguousStructure.get() != m_arrayStorageOrContiguousStructure.get()) {
             MacroAssembler::Jump bigLength = jit->m_jit.branch32(MacroAssembler::AboveOrEqual, m_sizeGPR, MacroAssembler::TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH));
-            jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_contiguousStructure), scratchGPR);
+            jit->m_jit.move(SpeculativeJIT::TrustedImmPtr(m_contiguousStructure), scratchGPR);
             MacroAssembler::Jump done = jit->m_jit.jump();
             bigLength.link(&jit->m_jit);
-            jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_arrayStorageOrContiguousStructure), scratchGPR);
+            jit->m_jit.move(SpeculativeJIT::TrustedImmPtr(m_arrayStorageOrContiguousStructure), scratchGPR);
             done.link(&jit->m_jit);
         } else
-            jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_contiguousStructure), scratchGPR);
+            jit->m_jit.move(SpeculativeJIT::TrustedImmPtr(m_contiguousStructure), scratchGPR);
         jit->callOperation(m_function, m_resultGPR, scratchGPR, m_sizeGPR, m_storageGPR);
         GPRReg canTrample = SpeculativeJIT::pickCanTrample(m_resultGPR);
         for (unsigned i = m_plans.size(); i--;)
@@ -117,8 +117,8 @@ protected:
 private:
     P_JITOperation_EStZB m_function;
     GPRReg m_resultGPR;
-    Structure* m_contiguousStructure;
-    Structure* m_arrayStorageOrContiguousStructure;
+    RegisteredStructure m_contiguousStructure;
+    RegisteredStructure m_arrayStorageOrContiguousStructure;
     GPRReg m_sizeGPR;
     GPRReg m_storageGPR;
     Vector<SilentRegisterSavePlan, 2> m_plans;
index 616518d..feed81f 100644 (file)
@@ -39,7 +39,7 @@ namespace JSC { namespace DFG {
 class CallCreateDirectArgumentsSlowPathGenerator : public JumpingSlowPathGenerator<MacroAssembler::JumpList> {
 public:
     CallCreateDirectArgumentsSlowPathGenerator(
-        MacroAssembler::JumpList from, SpeculativeJIT* jit, GPRReg resultGPR, Structure* structure,
+        MacroAssembler::JumpList from, SpeculativeJIT* jit, GPRReg resultGPR, RegisteredStructure structure,
         GPRReg lengthGPR, unsigned minCapacity)
         : JumpingSlowPathGenerator<MacroAssembler::JumpList>(from, jit)
         , m_resultGPR(resultGPR)
@@ -69,7 +69,7 @@ protected:
     
 private:
     GPRReg m_resultGPR;
-    Structure* m_structure;
+    RegisteredStructure m_structure;
     GPRReg m_lengthGPR;
     unsigned m_minCapacity;
     Vector<SilentRegisterSavePlan, 2> m_plans;
index ee7ec3b..42dd381 100644 (file)
@@ -43,8 +43,8 @@ void CommonData::notifyCompilingStructureTransition(Plan& plan, CodeBlock* codeB
     plan.transitions.addLazily(
         codeBlock,
         node->origin.semantic.codeOriginOwner(),
-        node->transition()->previous,
-        node->transition()->next);
+        node->transition()->previous.get(),
+        node->transition()->next.get());
 }
 
 CallSiteIndex CommonData::addCodeOrigin(CodeOrigin codeOrigin)
index b4ad484..92a38ec 100644 (file)
@@ -145,7 +145,7 @@ private:
             case CheckStructure:
             case ArrayifyToStructure: {
                 AbstractValue& value = m_state.forNode(node->child1());
-                StructureSet set;
+                RegisteredStructureSet set;
                 if (node->op() == ArrayifyToStructure)
                     set = node->structure();
                 else
@@ -206,11 +206,11 @@ private:
                 
             case CheckStructureImmediate: {
                 AbstractValue& value = m_state.forNode(node->child1());
-                StructureSet& set = node->structureSet();
+                const RegisteredStructureSet& set = node->structureSet();
                 
                 if (value.value()) {
                     if (Structure* structure = jsDynamicCast<Structure*>(value.value())) {
-                        if (set.contains(structure)) {
+                        if (set.contains(m_graph.registerStructure(structure))) {
                             m_interpreter.execute(indexInBlock);
                             node->remove();
                             eliminated = true;
@@ -225,7 +225,7 @@ private:
                         node,
                         [&] (Node* incoming) {
                             if (Structure* structure = incoming->dynamicCastConstant<Structure*>()) {
-                                if (set.contains(structure))
+                                if (set.contains(m_graph.registerStructure(structure)))
                                     return;
                             }
                             allGood = false;
@@ -421,7 +421,9 @@ private:
 
                 for (unsigned i = 0; i < data.variants.size(); ++i) {
                     PutByIdVariant& variant = data.variants[i];
-                    variant.oldStructure().filter(baseValue);
+                    variant.oldStructure().genericFilter([&] (Structure* structure) -> bool {
+                        return baseValue.contains(m_graph.registerStructure(structure));
+                    });
                     
                     if (variant.oldStructure().isEmpty()) {
                         data.variants[i--] = data.variants.last();
@@ -460,12 +462,12 @@ private:
                 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
                 alreadyHandled = true; // Don't allow the default constant folder to do things to this.
 
-                if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered()
+                if (!baseValue.m_structure.isFinite()
                     || (node->child1().useKind() == UntypedUse || (baseValue.m_type & ~SpecCell)))
                     break;
                 
                 GetByIdStatus status = GetByIdStatus::computeFor(
-                    baseValue.m_structure.set(), m_graph.identifiers()[identifierNumber]);
+                    baseValue.m_structure.toStructureSet(), m_graph.identifiers()[identifierNumber]);
                 if (!status.isSimple())
                     break;
                 
@@ -490,7 +492,7 @@ private:
                 for (const GetByIdVariant& variant : status.variants()) {
                     data->cases.append(
                         MultiGetByOffsetCase(
-                            variant.structureSet(),
+                            *m_graph.addStructureSet(variant.structureSet()),
                             GetByOffsetMethod::load(variant.offset())));
                 }
                 data->identifierNumber = identifierNumber;
@@ -515,12 +517,12 @@ private:
                 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
                 alreadyHandled = true; // Don't allow the default constant folder to do things to this.
 
-                if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered())
+                if (!baseValue.m_structure.isFinite())
                     break;
                 
                 PutByIdStatus status = PutByIdStatus::computeFor(
                     m_graph.globalObjectFor(origin.semantic),
-                    baseValue.m_structure.set(),
+                    baseValue.m_structure.toStructureSet(),
                     m_graph.identifiers()[identifierNumber],
                     node->op() == PutByIdDirect);
                 
@@ -713,7 +715,7 @@ private:
         // We aren't set up to handle prototype stuff.
         DFG_ASSERT(m_graph, node, variant.conditionSet().isEmpty());
 
-        if (JSValue value = m_graph.tryGetConstantProperty(baseValue.m_value, variant.structureSet(), variant.offset())) {
+        if (JSValue value = m_graph.tryGetConstantProperty(baseValue.m_value, *m_graph.addStructureSet(variant.structureSet()), variant.offset())) {
             m_graph.convertToConstant(node, m_graph.freeze(value));
             return;
         }
@@ -759,7 +761,7 @@ private:
         Transition* transition = 0;
         if (variant.kind() == PutByIdVariant::Transition) {
             transition = m_graph.m_transitions.add(
-                variant.oldStructureForTransition(), variant.newStructure());
+                m_graph.registerStructure(variant.oldStructureForTransition()), m_graph.registerStructure(variant.newStructure()));
         }
 
         Edge propertyStorage;
@@ -821,6 +823,12 @@ private:
     void addBaseCheck(
         unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const StructureSet& set)
     {
+        addBaseCheck(indexInBlock, node, baseValue, *m_graph.addStructureSet(set));
+    }
+
+    void addBaseCheck(
+        unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const RegisteredStructureSet& set)
+    {
         if (!baseValue.m_structure.isSubsetOf(set)) {
             // Arises when we prune MultiGetByOffset. We could have a
             // MultiGetByOffset with a single variant that checks for structure S,
@@ -828,7 +836,7 @@ private:
             ASSERT(node->child1());
             m_insertionSet.insertNode(
                 indexInBlock, SpecNone, CheckStructure, node->origin,
-                OpInfo(m_graph.addStructureSet(set)), node->child1());
+                OpInfo(m_graph.addStructureSet(set.toStructureSet())), node->child1());
             return;
         }
         
@@ -838,8 +846,12 @@ private:
     
     void addStructureTransitionCheck(NodeOrigin origin, unsigned indexInBlock, JSCell* cell, Structure* structure)
     {
-        if (m_graph.registerStructure(cell->structure()) == StructureRegisteredAndWatched)
-            return;
+        {
+            StructureRegistrationResult result;
+            m_graph.registerStructure(cell->structure(), result);
+            if (result == StructureRegisteredAndWatched)
+                return;
+        }
         
         m_graph.registerStructure(structure);
 
index 21306ac..29daf4b 100644 (file)
@@ -72,6 +72,12 @@ void DesiredWeakReferences::reallyAdd(VM& vm, CommonData* common)
             common->weakStructureReferences.append(
                 WriteBarrier<Structure>(vm, m_codeBlock, structure));
         } else {
+            // There are weird relationships in how optimized CodeBlocks
+            // point to other CodeBlocks. We don't want to have them be
+            // part of the weak pointer set. For example, an optimized CodeBlock
+            // having a weak pointer to itself will cause it to get collected.
+            RELEASE_ASSERT(!jsDynamicCast<CodeBlock*>(target));
+
             common->weakReferences.append(
                 WriteBarrier<JSCell>(vm, m_codeBlock, target));
         }
index 1ad7bc1..4b05bb3 100644 (file)
@@ -2365,7 +2365,7 @@ private:
                 if (structure) {
                     m_insertionSet.insertNode(
                         m_indexInBlock, SpecNone, ArrayifyToStructure, origin,
-                        OpInfo(structure), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
+                        OpInfo(m_graph.registerStructure(structure)), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
                 } else {
                     m_insertionSet.insertNode(
                         m_indexInBlock, SpecNone, Arrayify, origin,
index 7b798e3..4dd916a 100644 (file)
@@ -88,6 +88,10 @@ Graph::Graph(VM& vm, Plan& plan, LongLivedState& longLivedState)
     
     m_indexingCache = std::make_unique<FlowIndexing>(*this);
     m_abstractValuesCache = std::make_unique<FlowMap<AbstractValue>>(*this);
+
+    registerStructure(vm.structureStructure.get());
+    this->stringStructure = registerStructure(vm.stringStructure.get());
+    this->symbolStructure = registerStructure(vm.symbolStructure.get());
 }
 
 Graph::~Graph()
@@ -245,15 +249,15 @@ void Graph::dump(PrintStream& out, const char* prefix, Node* node, DumpContext*
     if (node->hasPromotedLocationDescriptor())
         out.print(comma, node->promotedLocationDescriptor());
     if (node->hasStructureSet())
-        out.print(comma, inContext(node->structureSet(), context));
+        out.print(comma, inContext(node->structureSet().toStructureSet(), context));
     if (node->hasStructure())
-        out.print(comma, inContext(*node->structure(), context));
+        out.print(comma, inContext(*node->structure().get(), context));
     if (node->hasTransition()) {
         out.print(comma, pointerDumpInContext(node->transition(), context));
 #if USE(JSVALUE64)
         out.print(", ID:", node->transition()->next->id());
 #else
-        out.print(", ID:", RawPointer(node->transition()->next));
+        out.print(", ID:", RawPointer(node->transition()->next.get()));
 #endif
     }
     if (node->hasCellOperand()) {
@@ -1207,7 +1211,7 @@ unsigned Graph::requiredRegisterCountForExecutionAndExit()
 }
 
 JSValue Graph::tryGetConstantProperty(
-    JSValue base, const StructureSet& structureSet, PropertyOffset offset)
+    JSValue base, const RegisteredStructureSet& structureSet, PropertyOffset offset)
 {
     if (!base || !base.isObject())
         return JSValue();
@@ -1215,8 +1219,7 @@ JSValue Graph::tryGetConstantProperty(
     JSObject* object = asObject(base);
     
     for (unsigned i = structureSet.size(); i--;) {
-        Structure* structure = structureSet[i];
-        assertIsRegistered(structure);
+        RegisteredStructure structure = structureSet[i];
         
         WatchpointSet* set = structure->propertyReplacementWatchpointSet(offset);
         if (!set || !set->isStillValid())
@@ -1248,7 +1251,7 @@ JSValue Graph::tryGetConstantProperty(
     // incompatible with the getDirect we're trying to do. The easiest way to do that is to
     // determine if the structure belongs to the proven set.
     
-    if (!structureSet.contains(object->structure()))
+    if (!structureSet.toStructureSet().contains(object->structure()))
         return JSValue();
     
     return object->getDirect(offset);
@@ -1256,7 +1259,7 @@ JSValue Graph::tryGetConstantProperty(
 
 JSValue Graph::tryGetConstantProperty(JSValue base, Structure* structure, PropertyOffset offset)
 {
-    return tryGetConstantProperty(base, StructureSet(structure), offset);
+    return tryGetConstantProperty(base, RegisteredStructureSet(registerStructure(structure)), offset);
 }
 
 JSValue Graph::tryGetConstantProperty(
@@ -1278,13 +1281,13 @@ JSValue Graph::tryGetConstantProperty(const AbstractValue& base, PropertyOffset
 }
 
 AbstractValue Graph::inferredValueForProperty(
-    const StructureSet& base, UniquedStringImpl* uid, StructureClobberState clobberState)
+    const RegisteredStructureSet& base, UniquedStringImpl* uid, StructureClobberState clobberState)
 {
     AbstractValue result;
     base.forEach(
-        [&] (Structure* structure) {
+        [&] (RegisteredStructure structure) {
             AbstractValue value;
-            value.set(*this, inferredTypeForProperty(structure, uid));
+            value.set(*this, inferredTypeForProperty(structure.get(), uid));
             result.merge(value);
         });
     if (clobberState == StructuresAreClobbered)
@@ -1413,61 +1416,18 @@ void Graph::visitChildren(SlotVisitor& visitor)
         visitor.appendUnbarriered(value->value());
         visitor.appendUnbarriered(value->structure());
     }
-    
-    for (BlockIndex blockIndex = numBlocks(); blockIndex--;) {
-        BasicBlock* block = this->block(blockIndex);
-        if (!block)
-            continue;
-        
-        for (auto* node : *block) {
-            switch (node->op()) {
-            case CheckStructure:
-                for (unsigned i = node->structureSet().size(); i--;)
-                    visitor.appendUnbarriered(node->structureSet()[i]);
-                break;
-                
-            case NewObject:
-            case ArrayifyToStructure:
-            case NewStringObject:
-                visitor.appendUnbarriered(node->structure());
-                break;
-                
-            case PutStructure:
-            case AllocatePropertyStorage:
-            case ReallocatePropertyStorage:
-                visitor.appendUnbarriered(node->transition()->previous);
-                visitor.appendUnbarriered(node->transition()->next);
-                break;
-                
-            case MultiGetByOffset:
-                for (const MultiGetByOffsetCase& getCase : node->multiGetByOffsetData().cases) {
-                    for (Structure* structure : getCase.set())
-                        visitor.appendUnbarriered(structure);
-                }
-                break;
-                    
-            case MultiPutByOffset:
-                for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
-                    PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
-                    const StructureSet& set = variant.oldStructure();
-                    for (unsigned j = set.size(); j--;)
-                        visitor.appendUnbarriered(set[j]);
-                    if (variant.kind() == PutByIdVariant::Transition)
-                        visitor.appendUnbarriered(variant.newStructure());
-                }
-                break;
-                
-            default:
-                break;
-            }
-        }
-    }
 }
 
 FrozenValue* Graph::freeze(JSValue value)
 {
     if (UNLIKELY(!value))
         return FrozenValue::emptySingleton();
+
+    // There are weird relationships in how optimized CodeBlocks
+    // point to other CodeBlocks. We don't want to have them be
+    // part of the weak pointer set. For example, an optimized CodeBlock
+    // having a weak pointer to itself will cause it to get collected.
+    RELEASE_ASSERT(!jsDynamicCast<CodeBlock*>(value));
     
     auto result = m_frozenValueMap.add(JSValue::encode(value), nullptr);
     if (LIKELY(!result.isNewEntry))
@@ -1507,12 +1467,14 @@ void Graph::convertToStrongConstant(Node* node, JSValue value)
     convertToConstant(node, freezeStrong(value));
 }
 
-StructureRegistrationResult Graph::registerStructure(Structure* structure)
+RegisteredStructure Graph::registerStructure(Structure* structure, StructureRegistrationResult& result)
 {
     m_plan.weakReferences.addLazily(structure);
     if (m_plan.watchpoints.consider(structure))
-        return StructureRegisteredAndWatched;
-    return StructureRegisteredNormally;
+        result = StructureRegisteredAndWatched;
+    else
+        result = StructureRegisteredNormally;
+    return RegisteredStructure::createPrivate(structure);
 }
 
 void Graph::assertIsRegistered(Structure* structure)
index d3047f3..6d52469 100644 (file)
@@ -213,7 +213,12 @@ public:
     void convertToConstant(Node* node, JSValue value);
     void convertToStrongConstant(Node* node, JSValue value);
     
-    StructureRegistrationResult registerStructure(Structure* structure);
+    RegisteredStructure registerStructure(Structure* structure)
+    {
+        StructureRegistrationResult ignored;
+        return registerStructure(structure, ignored);
+    }
+    RegisteredStructure registerStructure(Structure*, StructureRegistrationResult&);
     void assertIsRegistered(Structure* structure);
     
     // CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names).
@@ -341,12 +346,26 @@ public:
     
     static const char *opName(NodeType);
     
-    StructureSet* addStructureSet(const StructureSet& structureSet)
+    RegisteredStructureSet* addStructureSet(const StructureSet& structureSet)
     {
+        m_structureSets.append();
+        RegisteredStructureSet* result = &m_structureSets.last();
+
         for (Structure* structure : structureSet)
-            registerStructure(structure);
-        m_structureSet.append(structureSet);
-        return &m_structureSet.last();
+            result->add(registerStructure(structure));
+
+        return result;
+    }
+
+    RegisteredStructureSet* addStructureSet(const RegisteredStructureSet& structureSet)
+    {
+        m_structureSets.append();
+        RegisteredStructureSet* result = &m_structureSets.last();
+
+        for (RegisteredStructure structure : structureSet)
+            result->add(structure);
+
+        return result;
     }
     
     JSGlobalObject* globalObjectFor(CodeOrigin codeOrigin)
@@ -715,7 +734,7 @@ public:
     }
 
     AbstractValue inferredValueForProperty(
-        const StructureSet& base, UniquedStringImpl* uid, StructureClobberState = StructuresAreWatched);
+        const RegisteredStructureSet& 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.
@@ -818,7 +837,7 @@ public:
     unsigned requiredRegisterCountForExit();
     unsigned requiredRegisterCountForExecutionAndExit();
     
-    JSValue tryGetConstantProperty(JSValue base, const StructureSet&, PropertyOffset);
+    JSValue tryGetConstantProperty(JSValue base, const RegisteredStructureSet&, PropertyOffset);
     JSValue tryGetConstantProperty(JSValue base, Structure*, PropertyOffset);
     JSValue tryGetConstantProperty(JSValue base, const StructureAbstractValue&, PropertyOffset);
     JSValue tryGetConstantProperty(const AbstractValue&, PropertyOffset);
@@ -910,7 +929,6 @@ public:
     
     SegmentedVector<VariableAccessData, 16> m_variableAccessData;
     SegmentedVector<ArgumentPosition, 8> m_argumentPositions;
-    SegmentedVector<StructureSet, 16> m_structureSet;
     Bag<Transition> m_transitions;
     SegmentedVector<NewArrayBufferData, 4> m_newArrayBufferData;
     Bag<BranchData> m_branchData;
@@ -960,6 +978,9 @@ public:
     std::unique_ptr<FlowIndexing> m_indexingCache;
     std::unique_ptr<FlowMap<AbstractValue>> m_abstractValuesCache;
 
+    RegisteredStructure stringStructure;
+    RegisteredStructure symbolStructure;
+
 private:
     void addNodeToMapByIndex(Node*);
 
@@ -997,6 +1018,7 @@ private:
 
     Vector<Node*, 0, UnsafeVectorOverflow> m_nodesByIndex;
     Vector<unsigned, 0, UnsafeVectorOverflow> m_nodeIndexFreeList;
+    SegmentedVector<RegisteredStructureSet, 16> m_structureSets;
 };
 
 } } // namespace JSC::DFG
index 4f8e817..d868012 100644 (file)
@@ -242,14 +242,14 @@ public:
     }
 
     template<typename T>
-    Jump branchWeakStructure(RelationalCondition cond, T left, Structure* weakStructure)
+    Jump branchWeakStructure(RelationalCondition cond, T left, RegisteredStructure weakStructure)
     {
+        Structure* structure = weakStructure.get();
 #if USE(JSVALUE64)
-        Jump result = branch32(cond, left, TrustedImm32(weakStructure->id()));
-        addWeakReference(weakStructure);
+        Jump result = branch32(cond, left, TrustedImm32(structure->id()));
         return result;
 #else
-        return branchWeakPtr(cond, left, weakStructure);
+        return branchPtr(cond, left, TrustedImmPtr(structure));
 #endif
     }
 
index d1a111b..4dcab5f 100644 (file)
@@ -59,7 +59,7 @@ void GetByOffsetMethod::dump(PrintStream& out) const
 
 void MultiGetByOffsetCase::dumpInContext(PrintStream& out, DumpContext* context) const
 {
-    out.print(inContext(m_set, context), ":", inContext(m_method, context));
+    out.print(inContext(m_set.toStructureSet(), context), ":", inContext(m_method, context));
 }
 
 void MultiGetByOffsetCase::dump(PrintStream& out) const
index 853b508..d5ec0e0 100644 (file)
@@ -27,6 +27,7 @@
 
 #if ENABLE(DFG_JIT)
 
+#include "DFGRegisteredStructureSet.h"
 #include "DumpContext.h"
 #include "JSObject.h"
 #include "StructureSet.h"
@@ -119,21 +120,21 @@ public:
     {
     }
     
-    MultiGetByOffsetCase(const StructureSet& set, const GetByOffsetMethod& method)
+    MultiGetByOffsetCase(const RegisteredStructureSet& set, const GetByOffsetMethod& method)
         : m_set(set)
         , m_method(method)
     {
     }
     
-    StructureSet& set() { return m_set; }
-    const StructureSet& set() const { return m_set; }
+    RegisteredStructureSet& set() { return m_set; }
+    const RegisteredStructureSet& set() const { return m_set; }
     const GetByOffsetMethod& method() const { return m_method; }
     
     void dumpInContext(PrintStream&, DumpContext*) const;
     void dump(PrintStream&) const;
 
 private:
-    StructureSet m_set;
+    RegisteredStructureSet m_set;
     GetByOffsetMethod m_method;
 };
 
index 6a94b59..76cc0da 100644 (file)
@@ -175,7 +175,7 @@ void Node::convertToPutHint(const PromotedLocationDescriptor& descriptor, Node*
 void Node::convertToPutStructureHint(Node* structure)
 {
     ASSERT(m_op == PutStructure);
-    ASSERT(structure->castConstant<Structure*>() == transition()->next);
+    ASSERT(structure->castConstant<Structure*>() == transition()->next.get());
     convertToPutHint(StructurePLoc, child1().node(), structure);
 }
 
index b28157f..43c20f5 100644 (file)
@@ -42,6 +42,8 @@
 #include "DFGNodeType.h"
 #include "DFGObjectMaterializationData.h"
 #include "DFGOpInfo.h"
+#include "DFGRegisteredStructure.h"
+#include "DFGRegisteredStructureSet.h"
 #include "DFGTransition.h"
 #include "DFGUseKind.h"
 #include "DFGVariableAccessData.h"
@@ -410,10 +412,10 @@ public:
 
     void remove();
 
-    void convertToCheckStructure(StructureSet* set)
+    void convertToCheckStructure(RegisteredStructureSet* set)
     {
         setOpAndDefaultFlags(CheckStructure);
-        m_opInfo = set; 
+        m_opInfo = set;
     }
 
     void convertToCheckStructureImmediate(Node* structure)
@@ -1614,10 +1616,10 @@ public:
         }
     }
     
-    StructureSet& structureSet()
+    const RegisteredStructureSet& structureSet()
     {
         ASSERT(hasStructureSet());
-        return *m_opInfo.as<StructureSet*>();
+        return *m_opInfo.as<RegisteredStructureSet*>();
     }
     
     bool hasStructure()
@@ -1632,10 +1634,10 @@ public:
         }
     }
     
-    Structure* structure()
+    RegisteredStructure structure()
     {
         ASSERT(hasStructure());
-        return m_opInfo.as<Structure*>();
+        return m_opInfo.asRegisteredStructure();
     }
     
     bool hasStorageAccessData()
@@ -2513,6 +2515,11 @@ private:
             u.int64 = 0;
             u.constPointer = constPointer;
         }
+        OpInfoWrapper(RegisteredStructure structure)
+        {
+            u.int64 = 0;
+            u.pointer = bitwise_cast<void*>(structure);
+        }
         OpInfoWrapper& operator=(uint32_t int32)
         {
             u.int64 = 0;
@@ -2542,6 +2549,12 @@ private:
             u.constPointer = constPointer;
             return *this;
         }
+        OpInfoWrapper& operator=(RegisteredStructure structure)
+        {
+            u.int64 = 0;
+            u.pointer = bitwise_cast<void*>(structure);
+            return *this;
+        }
         template <typename T>
         ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_pointer<T>::value && !std::is_const<typename std::remove_pointer<T>::type>::value, T>::type
         {
@@ -2562,6 +2575,11 @@ private:
         {
             return u.int64;
         }
+        ALWAYS_INLINE RegisteredStructure asRegisteredStructure() const
+        {
+            return bitwise_cast<RegisteredStructure>(u.pointer);
+        }
+
         union {
             uint32_t int32;
             uint64_t int64;
index b7bde89..0d0d54d 100644 (file)
@@ -186,28 +186,28 @@ public:
         }
     }
 
-    Allocation& setStructures(const StructureSet& structures)
+    Allocation& setStructures(const RegisteredStructureSet& structures)
     {
         ASSERT(hasStructures() && !structures.isEmpty());
         m_structures = structures;
         return *this;
     }
 
-    Allocation& mergeStructures(const StructureSet& structures)
+    Allocation& mergeStructures(const RegisteredStructureSet& structures)
     {
         ASSERT(hasStructures() || structures.isEmpty());
         m_structures.merge(structures);
         return *this;
     }
 
-    Allocation& filterStructures(const StructureSet& structures)
+    Allocation& filterStructures(const RegisteredStructureSet& structures)
     {
         ASSERT(hasStructures());
         m_structures.filter(structures);
         return *this;
     }
 
-    const StructureSet& structures() const
+    const RegisteredStructureSet& structures() const
     {
         return m_structures;
     }
@@ -283,7 +283,7 @@ public:
         }
         out.print("Allocation(");
         if (!m_structures.isEmpty())
-            out.print(inContext(m_structures, context));
+            out.print(inContext(m_structures.toStructureSet(), context));
         if (!m_fields.isEmpty()) {
             if (!m_structures.isEmpty())
                 out.print(", ");
@@ -296,7 +296,7 @@ private:
     Node* m_identifier; // This is the actual node that created the allocation
     Kind m_kind;
     HashMap<PromotedLocationDescriptor, Node*> m_fields;
-    StructureSet m_structures;
+    RegisteredStructureSet m_structures;
 };
 
 class LocalHeap {
@@ -832,7 +832,7 @@ private:
             target = &m_heap.newAllocation(node, Allocation::Kind::Object);
             target->setStructures(node->structure());
             writes.add(
-                StructurePLoc, LazyNode(m_graph.freeze(node->structure())));
+                StructurePLoc, LazyNode(m_graph.freeze(node->structure().get())));
             break;
 
         case NewFunction:
@@ -879,7 +879,7 @@ private:
         case PutStructure:
             target = m_heap.onlyLocalAllocation(node->child1().node());
             if (target && target->isObjectAllocation()) {
-                writes.add(StructurePLoc, LazyNode(m_graph.freeze(JSValue(node->transition()->next))));
+                writes.add(StructurePLoc, LazyNode(m_graph.freeze(JSValue(node->transition()->next.get()))));
                 target->setStructures(node->transition()->next);
             } else
                 m_heap.escape(node->child1().node());
@@ -912,7 +912,7 @@ private:
             Allocation* allocation = m_heap.onlyLocalAllocation(node->child1().node());
             if (allocation && allocation->isObjectAllocation()) {
                 MultiGetByOffsetData& data = node->multiGetByOffsetData();
-                StructureSet validStructures;
+                RegisteredStructureSet validStructures;
                 bool hasInvalidStructures = false;
                 for (const auto& multiGetByOffsetCase : data.cases) {
                     if (!allocation->structures().overlaps(multiGetByOffsetCase.set()))
@@ -1444,12 +1444,11 @@ private:
         switch (allocation.kind()) {
         case Allocation::Kind::Object: {
             ObjectMaterializationData* data = m_graph.m_objectMaterializationData.add();
-            StructureSet* set = m_graph.addStructureSet(allocation.structures());
 
             return m_graph.addNode(
                 allocation.identifier()->prediction(), Node::VarArg, MaterializeNewObject,
                 where->origin.withSemantic(allocation.identifier()->origin.semantic),
-                OpInfo(set), OpInfo(data), 0, 0);
+                OpInfo(m_graph.addStructureSet(allocation.structures())), OpInfo(data), 0, 0);
         }
 
         case Allocation::Kind::AsyncFunction:
@@ -2103,7 +2102,7 @@ private:
         case NamedPropertyPLoc: {
             Allocation& allocation = m_heap.getAllocation(location.base());
 
-            Vector<Structure*> structures;
+            Vector<RegisteredStructure> structures;
             structures.appendRange(allocation.structures().begin(), allocation.structures().end());
             unsigned identifierNumber = location.info();
             UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
@@ -2111,7 +2110,7 @@ private:
             std::sort(
                 structures.begin(),
                 structures.end(),
-                [uid] (Structure *a, Structure* b) -> bool {
+                [uid] (RegisteredStructure a, RegisteredStructure b) -> bool {
                     return a->getConcurrently(uid) < b->getConcurrently(uid);
                 });
 
@@ -2142,7 +2141,7 @@ private:
             {
                 PropertyOffset currentOffset = firstOffset;
                 StructureSet currentSet;
-                for (Structure* structure : structures) {
+                for (RegisteredStructure structure : structures) {
                     PropertyOffset offset = structure->getConcurrently(uid);
                     if (offset != currentOffset) {
                         // Because our analysis treats MultiPutByOffset like an escape, we only have to
@@ -2155,7 +2154,7 @@ private:
                         currentOffset = offset;
                         currentSet.clear();
                     }
-                    currentSet.add(structure);
+                    currentSet.add(structure.get());
                 }
                 data->variants.append(
                     PutByIdVariant::replace(currentSet, currentOffset, InferredType::Top));
index 57f3329..ddccfb1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -25,6 +25,8 @@
 
 #pragma once
 
+#include "DFGRegisteredStructure.h"
+#include "HeapCell.h"
 #include <wtf/StdLibExtras.h>
 
 #if ENABLE(DFG_JIT)
@@ -42,8 +44,17 @@ struct OpInfo {
 #if OS(DARWIN)
     explicit OpInfo(uintptr_t value) : m_value(static_cast<uint64_t>(value)) { }
 #endif
-    explicit OpInfo(void* value) : m_value(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(value))) { }
-    explicit OpInfo(const void* value) : m_value(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(value))) { }
+    explicit OpInfo(RegisteredStructure structure) : m_value(static_cast<uint64_t>(bitwise_cast<uintptr_t>(structure))) { }
+
+
+    template <typename T>
+    explicit OpInfo(T* ptr)
+    {
+        static_assert(!std::is_base_of<HeapCell, T>::value, "To make an OpInfo with a cell in it, the cell must be registered or frozen.");
+        static_assert(!std::is_base_of<StructureSet, T>::value, "To make an OpInfo with a structure set in, make sure to use RegisteredStructureSet.");
+        m_value = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(ptr));
+    }
+
     uint64_t m_value;
 };
 
index c128c3f..0307dc6 100644 (file)
@@ -67,7 +67,6 @@
 #include "DFGStoreBarrierClusteringPhase.h"
 #include "DFGStoreBarrierInsertionPhase.h"
 #include "DFGStrengthReductionPhase.h"
-#include "DFGStructureRegistrationPhase.h"
 #include "DFGTierUpCheckInjectionPhase.h"
 #include "DFGTypeCheckHoistingPhase.h"
 #include "DFGUnificationPhase.h"
@@ -311,7 +310,6 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState)
     RUN_PHASE(performBackwardsPropagation);
     RUN_PHASE(performPredictionPropagation);
     RUN_PHASE(performFixup);
-    RUN_PHASE(performStructureRegistration);
     RUN_PHASE(performInvalidationPointInjection);
     RUN_PHASE(performTypeCheckHoisting);
     
@@ -608,6 +606,11 @@ CompilationResult Plan::finalizeWithoutNotifyingCallback()
             trackedReferences.add(reference.get());
         for (WriteBarrier<Unknown>& constant : codeBlock->constants())
             trackedReferences.add(constant.get());
+
+        for (auto* inlineCallFrame : *inlineCallFrames) {
+            ASSERT(inlineCallFrame->baselineCodeBlock.get());
+            trackedReferences.add(inlineCallFrame->baselineCodeBlock.get());
+        }
         
         // Check that any other references that we have anywhere in the JITCode are also
         // tracked either strongly or weakly.
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #if ENABLE(DFG_JIT)
 
+#include "Structure.h"
+#include "StructureSet.h"
+
 namespace JSC { namespace DFG {
 
 class Graph;
 
-// Registers any structures we know about as weak references, and sets watchpoints on any
-// such structures that we know of that are currently watchable. It's somewhat
-// counterintuitive, but this ends up being the cleanest and most effective way of reducing
-// structure checks on terminal structures:
-//
-// - We used to only set watchpoints on watchable structures if we knew that this would
-//   remove a structure check. Experiments show that switching from that, to blindly
-//   setting watchpoints on all watchable structures, was not a regression.
-//
-// - It makes abstract interpretation a whole lot easier. We just assume that watchable
-//   structures are unclobberable without having to do any other logic.
-
-bool performStructureRegistration(Graph&);
+class RegisteredStructure {
+public:
+    RegisteredStructure() = default;
+
+    ALWAYS_INLINE Structure* get() const { return m_structure; }
+    Structure* operator->() const { return get(); }
+
+    bool operator==(const RegisteredStructure& other) const
+    {
+        return get() == other.get();
+    }
+
+    bool operator!=(const RegisteredStructure& other) const
+    {
+        return !(*this == other);
+    }
+
+    explicit operator bool() const
+    {
+        return !!get();
+    }
+
+private:
+    friend class Graph;
+
+    RegisteredStructure(Structure* structure)
+        : m_structure(structure)
+    {
+        ASSERT(structure);
+    }
+
+    static RegisteredStructure createPrivate(Structure* structure)
+    {
+        return RegisteredStructure(structure);
+    }
+
+    Structure* m_structure { nullptr };
+};
 
 } } // namespace JSC::DFG
 
diff --git a/Source/JavaScriptCore/dfg/DFGRegisteredStructureSet.cpp b/Source/JavaScriptCore/dfg/DFGRegisteredStructureSet.cpp
new file mode 100644 (file)
index 0000000..e7a5891
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "DFGRegisteredStructureSet.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGAbstractValue.h"
+#include "TrackedReferences.h"
+
+namespace JSC { namespace DFG {
+
+void RegisteredStructureSet::filter(const DFG::StructureAbstractValue& other)
+{
+    genericFilter(
+        [&] (RegisteredStructure structure) -> bool {
+            return other.contains(structure); 
+        });
+}
+
+void RegisteredStructureSet::filter(SpeculatedType type)
+{
+    genericFilter(
+        [&] (RegisteredStructure structure) -> bool {
+            return type & speculationFromStructure(structure.get());
+        });
+}
+
+void RegisteredStructureSet::filterArrayModes(ArrayModes arrayModes)
+{
+    genericFilter(
+        [&] (RegisteredStructure structure) -> bool {
+            return arrayModes & arrayModeFromStructure(structure.get());
+        });
+}
+
+void RegisteredStructureSet::filter(const DFG::AbstractValue& other)
+{
+    filter(other.m_structure);
+    filter(other.m_type);
+    filterArrayModes(other.m_arrayModes);
+}
+
+SpeculatedType RegisteredStructureSet::speculationFromStructures() const
+{
+    SpeculatedType result = SpecNone;
+    forEach(
+        [&] (RegisteredStructure structure) {
+            mergeSpeculation(result, speculationFromStructure(structure.get()));
+        });
+    return result;
+}
+
+ArrayModes RegisteredStructureSet::arrayModesFromStructures() const
+{
+    ArrayModes result = 0;
+    forEach(
+        [&] (RegisteredStructure structure) {
+            mergeArrayModes(result, asArrayModes(structure->indexingType()));
+        });
+    return result;
+}
+
+void RegisteredStructureSet::validateReferences(const TrackedReferences& trackedReferences) const
+{
+    // The type system should help us here, but protect people from getting that wrong using bitwise_cast or something crazy.
+    forEach(
+        [&] (RegisteredStructure structure) {
+            trackedReferences.check(structure.get());
+        });
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
diff --git a/Source/JavaScriptCore/dfg/DFGRegisteredStructureSet.h b/Source/JavaScriptCore/dfg/DFGRegisteredStructureSet.h
new file mode 100644 (file)
index 0000000..11ea39f
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 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. 
+ */
+
+#pragma once
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGRegisteredStructure.h"
+#include "StructureSet.h"
+#include <wtf/TinyPtrSet.h>
+
+namespace JSC {
+
+class TrackedReferences;
+
+namespace DFG {
+
+struct AbstractValue;
+class StructureAbstractValue;
+
+class RegisteredStructureSet : public TinyPtrSet<RegisteredStructure> {
+public:
+
+    RegisteredStructureSet()
+    { }
+    
+    RegisteredStructureSet(RegisteredStructure structure)
+        : TinyPtrSet(structure)
+    {
+    }
+    
+    ALWAYS_INLINE RegisteredStructureSet(const RegisteredStructureSet& other)
+        : TinyPtrSet(other)
+    {
+    }
+    
+    RegisteredStructure onlyStructure() const
+    {
+        return onlyEntry();
+    }
+
+    StructureSet toStructureSet() const
+    {
+        StructureSet result;
+        forEach([&] (RegisteredStructure structure) { result.add(structure.get()); });
+        return result;
+    }
+
+    void filter(const DFG::StructureAbstractValue&);
+    void filter(SpeculatedType);
+    void filterArrayModes(ArrayModes);
+    void filter(const DFG::AbstractValue&);
+    
+    SpeculatedType speculationFromStructures() const;
+    ArrayModes arrayModesFromStructures() const;
+
+    void validateReferences(const TrackedReferences&) const;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
index 7b5af95..6b57579 100644 (file)
@@ -425,7 +425,7 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node)
     case AllocatePropertyStorage:
     case ReallocatePropertyStorage:
         return state.forNode(node->child1()).m_structure.isSubsetOf(
-            StructureSet(node->transition()->previous));
+            RegisteredStructureSet(node->transition()->previous));
         
     case GetByOffset:
     case GetGetterSetterByOffset:
index 05d76fa..0aee08d 100644 (file)
@@ -84,7 +84,7 @@ SpeculativeJIT::~SpeculativeJIT()
 {
 }
 
-void SpeculativeJIT::emitAllocateRawObject(GPRReg resultGPR, Structure* structure, GPRReg storageGPR, unsigned numElements, unsigned vectorLength)
+void SpeculativeJIT::emitAllocateRawObject(GPRReg resultGPR, RegisteredStructure structure, GPRReg storageGPR, unsigned numElements, unsigned vectorLength)
 {
     IndexingType indexingType = structure->indexingType();
     bool hasIndexingHeader = hasIndexedProperties(indexingType);
@@ -98,7 +98,7 @@ void SpeculativeJIT::emitAllocateRawObject(GPRReg resultGPR, Structure* structur
     GPRReg scratch2GPR = scratch2.gpr();
 
     ASSERT(vectorLength >= numElements);
-    vectorLength = Butterfly::optimalContiguousVectorLength(structure, vectorLength);
+    vectorLength = Butterfly::optimalContiguousVectorLength(structure.get(), vectorLength);
     
     JITCompiler::JumpList slowCases;
 
@@ -195,7 +195,7 @@ void SpeculativeJIT::emitGetCallee(CodeOrigin origin, GPRReg calleeGPR)
                 calleeGPR);
         } else {
             m_jit.move(
-                TrustedImmPtr(origin.inlineCallFrame->calleeRecovery.constant().asCell()),
+                TrustedImmPtr::weakPointer(m_jit.graph(), origin.inlineCallFrame->calleeRecovery.constant().asCell()),
                 calleeGPR);
         }
     } else
@@ -648,7 +648,8 @@ void SpeculativeJIT::silentFill(const SilentRegisterSavePlan& plan, GPRReg canTr
         m_jit.move(TrustedImm32(plan.node()->asBoolean()), plan.gpr());
         break;
     case SetCellConstant:
-        m_jit.move(TrustedImmPtr(plan.node()->asCell()), plan.gpr());
+        ASSERT(plan.node()->constant()->value().isCell());
+        m_jit.move(TrustedImmPtr(plan.node()->constant()), plan.gpr());
         break;
 #if USE(JSVALUE64)
     case SetTrustedJSConstant:
@@ -877,7 +878,7 @@ void SpeculativeJIT::checkArray(Node* node)
         m_jit.branchPtr(
             MacroAssembler::NotEqual,
             MacroAssembler::Address(temp.gpr(), Structure::classInfoOffset()),
-            MacroAssembler::TrustedImmPtr(expectedClassInfo)));
+            TrustedImmPtr(expectedClassInfo)));
     
     noResult(m_currentNode);
 }
@@ -2055,7 +2056,7 @@ void SpeculativeJIT::compileGetByValOnString(Node* node)
     cont8Bit.link(&m_jit);
 
     m_jit.lshift32(MacroAssembler::TrustedImm32(sizeof(void*) == 4 ? 2 : 3), scratchReg);
-    m_jit.addPtr(MacroAssembler::TrustedImmPtr(m_jit.vm()->smallStrings.singleCharacterStrings()), scratchReg);
+    m_jit.addPtr(TrustedImmPtr(m_jit.vm()->smallStrings.singleCharacterStrings()), scratchReg);
     m_jit.loadPtr(scratchReg, scratchReg);
 
     addSlowPathGenerator(
@@ -2146,7 +2147,7 @@ void SpeculativeJIT::compileFromCharCode(Node* node)
 
     JITCompiler::JumpList slowCases;
     slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, TrustedImm32(0xff)));
-    m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.vm()->smallStrings.singleCharacterStrings()), smallStringsReg);
+    m_jit.move(TrustedImmPtr(m_jit.vm()->smallStrings.singleCharacterStrings()), smallStringsReg);
     m_jit.loadPtr(MacroAssembler::BaseIndex(smallStringsReg, propertyReg, MacroAssembler::ScalePtr, 0), scratchReg);
 
     slowCases.append(m_jit.branchTest32(MacroAssembler::Zero, scratchReg));
@@ -2468,7 +2469,7 @@ void SpeculativeJIT::compileDoubleRep(Node* node)
             JITCompiler::Jump isUndefined = m_jit.branch64(JITCompiler::Equal, op1GPR, TrustedImm64(ValueUndefined));
 
             static const double zero = 0;
-            m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&zero), resultFPR);
+            m_jit.loadDouble(TrustedImmPtr(&zero), resultFPR);
 
             JITCompiler::Jump isNull = m_jit.branch64(JITCompiler::Equal, op1GPR, TrustedImm64(ValueNull));
             done.append(isNull);
@@ -2478,13 +2479,13 @@ void SpeculativeJIT::compileDoubleRep(Node* node)
 
             JITCompiler::Jump isFalse = m_jit.branch64(JITCompiler::Equal, op1GPR, TrustedImm64(ValueFalse));
             static const double one = 1;
-            m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&one), resultFPR);
+            m_jit.loadDouble(TrustedImmPtr(&one), resultFPR);
             done.append(m_jit.jump());
             done.append(isFalse);
 
             isUndefined.link(&m_jit);
             static const double NaN = PNaN;
-            m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&NaN), resultFPR);
+            m_jit.loadDouble(TrustedImmPtr(&NaN), resultFPR);
             done.append(m_jit.jump());
 
             isNumber.link(&m_jit);
@@ -2517,7 +2518,7 @@ void SpeculativeJIT::compileDoubleRep(Node* node)
             JITCompiler::Jump isUndefined = m_jit.branch32(JITCompiler::Equal, op1TagGPR, TrustedImm32(JSValue::UndefinedTag));
 
             static const double zero = 0;
-            m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&zero), resultFPR);
+            m_jit.loadDouble(TrustedImmPtr(&zero), resultFPR);
 
             JITCompiler::Jump isNull = m_jit.branch32(JITCompiler::Equal, op1TagGPR, TrustedImm32(JSValue::NullTag));
             done.append(isNull);
@@ -2526,13 +2527,13 @@ void SpeculativeJIT::compileDoubleRep(Node* node)
 
             JITCompiler::Jump isFalse = m_jit.branchTest32(JITCompiler::Zero, op1PayloadGPR, TrustedImm32(1));
             static const double one = 1;
-            m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&one), resultFPR);
+            m_jit.loadDouble(TrustedImmPtr(&one), resultFPR);
             done.append(m_jit.jump());
             done.append(isFalse);
 
             isUndefined.link(&m_jit);
             static const double NaN = PNaN;
-            m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&NaN), resultFPR);
+            m_jit.loadDouble(TrustedImmPtr(&NaN), resultFPR);
             done.append(m_jit.jump());
 
             isNumber.link(&m_jit);
@@ -2647,12 +2648,12 @@ static void compileClampDoubleToByte(JITCompiler& jit, GPRReg result, FPRReg sou
     static const double zero = 0;
     static const double byteMax = 255;
     static const double half = 0.5;
-    jit.loadDouble(MacroAssembler::TrustedImmPtr(&zero), scratch);
+    jit.loadDouble(JITCompiler::TrustedImmPtr(&zero), scratch);
     MacroAssembler::Jump tooSmall = jit.branchDouble(MacroAssembler::DoubleLessThanOrEqualOrUnordered, source, scratch);
-    jit.loadDouble(MacroAssembler::TrustedImmPtr(&byteMax), scratch);
+    jit.loadDouble(JITCompiler::TrustedImmPtr(&byteMax), scratch);
     MacroAssembler::Jump tooBig = jit.branchDouble(MacroAssembler::DoubleGreaterThan, source, scratch);
     
-    jit.loadDouble(MacroAssembler::TrustedImmPtr(&half), scratch);
+    jit.loadDouble(JITCompiler::TrustedImmPtr(&half), scratch);
     // FIXME: This should probably just use a floating point round!
     // https://bugs.webkit.org/show_bug.cgi?id=72054
     jit.addDouble(source, scratch);
@@ -3900,7 +3901,7 @@ void SpeculativeJIT::compileMakeRope(Node* node)
     MarkedAllocator* markedAllocator = subspaceFor<JSString>(*m_jit.vm())->allocatorFor(sizeof(JSRopeString));
     RELEASE_ASSERT(markedAllocator);
     m_jit.move(TrustedImmPtr(markedAllocator), allocatorGPR);
-    emitAllocateJSCell(resultGPR, markedAllocator, allocatorGPR, TrustedImmPtr(m_jit.vm()->stringStructure.get()), scratchGPR, slowPath);
+    emitAllocateJSCell(resultGPR, markedAllocator, allocatorGPR, TrustedImmPtr(m_jit.graph().registerStructure(m_jit.vm()->stringStructure.get())), scratchGPR, slowPath);
         
     m_jit.storePtr(TrustedImmPtr(0), JITCompiler::Address(resultGPR, JSString::offsetOfValue()));
     for (unsigned i = 0; i < numOpGPRs; ++i)
@@ -5097,7 +5098,7 @@ void SpeculativeJIT::compileArithRounding(Node* node)
                 FPRReg resultFPR = result.fpr();
                 if (producesInteger(node->arithRoundingMode()) && !shouldCheckNegativeZero(node->arithRoundingMode())) {
                     static const double halfConstant = 0.5;
-                    m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&halfConstant), resultFPR);
+                    m_jit.loadDouble(TrustedImmPtr(&halfConstant), resultFPR);
                     m_jit.addDouble(valueFPR, resultFPR);
                     m_jit.floorDouble(resultFPR, resultFPR);
                 } else {
@@ -5109,11 +5110,11 @@ void SpeculativeJIT::compileArithRounding(Node* node)
                     FPRTemporary scratch(this);
                     FPRReg scratchFPR = scratch.fpr();
                     static const double halfConstant = 0.5;
-                    m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&halfConstant), scratchFPR);
+                    m_jit.loadDouble(TrustedImmPtr(&halfConstant), scratchFPR);
 
                     JITCompiler::Jump shouldUseCeiled = m_jit.branchDouble(JITCompiler::DoubleLessThanOrEqual, realPartFPR, scratchFPR);
                     static const double oneConstant = -1.0;
-                    m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&oneConstant), scratchFPR);
+                    m_jit.loadDouble(TrustedImmPtr(&oneConstant), scratchFPR);
                     m_jit.addDouble(scratchFPR, resultFPR);
                     shouldUseCeiled.link(&m_jit);
                 }
@@ -6353,12 +6354,12 @@ void SpeculativeJIT::compileCheckStringIdent(Node* node)
     noResult(node);
 }
 
-template <typename ClassType> void SpeculativeJIT::compileNewFunctionCommon(GPRReg resultGPR, Structure* structure, GPRReg scratch1GPR, GPRReg scratch2GPR, GPRReg scopeGPR, MacroAssembler::JumpList& slowPath, size_t size, FunctionExecutable* executable, ptrdiff_t offsetOfScopeChain, ptrdiff_t offsetOfExecutable, ptrdiff_t offsetOfRareData)
+template <typename ClassType> void SpeculativeJIT::compileNewFunctionCommon(GPRReg resultGPR, RegisteredStructure structure, GPRReg scratch1GPR, GPRReg scratch2GPR, GPRReg scopeGPR, MacroAssembler::JumpList& slowPath, size_t size, FunctionExecutable* executable, ptrdiff_t offsetOfScopeChain, ptrdiff_t offsetOfExecutable, ptrdiff_t offsetOfRareData)
 {
     emitAllocateJSObjectWithKnownSize<ClassType>(resultGPR, TrustedImmPtr(structure), TrustedImmPtr(0), scratch1GPR, scratch2GPR, slowPath, size);
     
     m_jit.storePtr(scopeGPR, JITCompiler::Address(resultGPR, offsetOfScopeChain));
-    m_jit.storePtr(TrustedImmPtr(executable), JITCompiler::Address(resultGPR, offsetOfExecutable));
+    m_jit.storePtr(TrustedImmPtr::weakPointer(m_jit.graph(), executable), JITCompiler::Address(resultGPR, offsetOfExecutable));
     m_jit.storePtr(TrustedImmPtr(0), JITCompiler::Address(resultGPR, offsetOfRareData));
     
     m_jit.mutatorFence();
@@ -6391,10 +6392,10 @@ void SpeculativeJIT::compileNewFunction(Node* node)
         return;
     }
 
-    Structure* structure =
+    RegisteredStructure structure = m_jit.graph().registerStructure(
         nodeType == NewGeneratorFunction ? m_jit.graph().globalObjectFor(node->origin.semantic)->generatorFunctionStructure() :
         nodeType == NewAsyncFunction ? m_jit.graph().globalObjectFor(node->origin.semantic)->asyncFunctionStructure() :
-        m_jit.graph().globalObjectFor(node->origin.semantic)->functionStructure();
+        m_jit.graph().globalObjectFor(node->origin.semantic)->functionStructure());
     
     GPRTemporary result(this);
     GPRTemporary scratch1(this);
@@ -6510,8 +6511,8 @@ void SpeculativeJIT::compileForwardVarargs(Node* node)
 void SpeculativeJIT::compileCreateActivation(Node* node)
 {
     SymbolTable* table = node->castOperand<SymbolTable*>();
-    Structure* structure = m_jit.graph().globalObjectFor(
-        node->origin.semantic)->activationStructure();
+    RegisteredStructure structure = m_jit.graph().registerStructure(m_jit.graph().globalObjectFor(
+        node->origin.semantic)->activationStructure());
         
     SpeculateCellOperand scope(this, node->child1());
     GPRReg scopeGPR = scope.gpr();
@@ -6552,7 +6553,7 @@ void SpeculativeJIT::compileCreateActivation(Node* node)
     // activation must be young.
     m_jit.storePtr(scopeGPR, JITCompiler::Address(resultGPR, JSScope::offsetOfNext()));
     m_jit.storePtr(
-        TrustedImmPtr(table),
+        TrustedImmPtr(node->cellOperand()),
         JITCompiler::Address(resultGPR, JSLexicalEnvironment::offsetOfSymbolTable()));
         
     // Must initialize all members to undefined or the TDZ empty value.
@@ -6615,8 +6616,8 @@ void SpeculativeJIT::compileCreateDirectArguments(Node* node)
         m_jit.sub32(TrustedImm32(1), lengthGPR);
     }
         
-    Structure* structure =
-        m_jit.graph().globalObjectFor(node->origin.semantic)->directArgumentsStructure();
+    RegisteredStructure structure =
+        m_jit.graph().registerStructure(m_jit.graph().globalObjectFor(node->origin.semantic)->directArgumentsStructure());
         
     // Use a different strategy for allocating the object depending on whether we know its
     // size statically.
@@ -6681,8 +6682,8 @@ void SpeculativeJIT::compileCreateDirectArguments(Node* node)
                 scratch1GPR);
         } else {
             m_jit.move(
-                TrustedImmPtr(
-                    node->origin.semantic.inlineCallFrame->calleeRecovery.constant().asCell()),
+                TrustedImmPtr::weakPointer(
+                    m_jit.graph(), node->origin.semantic.inlineCallFrame->calleeRecovery.constant().asCell()),
                 scratch1GPR);
         }
     } else
@@ -6798,7 +6799,7 @@ void SpeculativeJIT::compileCreateScopedArguments(Node* node)
     m_jit.setupArgument(
         1, [&] (GPRReg destGPR) {
             m_jit.move(
-                TrustedImmPtr(m_jit.globalObjectFor(node->origin.semantic)->scopedArgumentsStructure()),
+                TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.globalObjectFor(node->origin.semantic)->scopedArgumentsStructure()),
                 destGPR);
         });
     m_jit.setupArgument(0, [&] (GPRReg destGPR) { m_jit.move(GPRInfo::callFrameRegister, destGPR); });
@@ -6825,8 +6826,8 @@ void SpeculativeJIT::compileCreateClonedArguments(Node* node)
     m_jit.setupArgument(
         1, [&] (GPRReg destGPR) {
             m_jit.move(
-                TrustedImmPtr(
-                    m_jit.globalObjectFor(node->origin.semantic)->clonedArgumentsStructure()),
+                TrustedImmPtr::weakPointer(
+                    m_jit.graph(), m_jit.globalObjectFor(node->origin.semantic)->clonedArgumentsStructure()),
                 destGPR);
         });
     m_jit.setupArgument(0, [&] (GPRReg destGPR) { m_jit.move(GPRInfo::callFrameRegister, destGPR); });
@@ -6949,7 +6950,7 @@ void SpeculativeJIT::compileSpread(Node* node)
         m_jit.lshift32(TrustedImm32(3), scratch1GPR);
         m_jit.add32(TrustedImm32(JSFixedArray::offsetOfData()), scratch1GPR);
 
-        m_jit.emitAllocateVariableSizedCell<JSFixedArray>(resultGPR, TrustedImmPtr(m_jit.graph().m_vm.fixedArrayStructure.get()), scratch1GPR, scratch1GPR, scratch2GPR, slowPath);
+        m_jit.emitAllocateVariableSizedCell<JSFixedArray>(resultGPR, TrustedImmPtr(m_jit.graph().registerStructure(m_jit.graph().m_vm.fixedArrayStructure.get())), scratch1GPR, scratch1GPR, scratch2GPR, slowPath);
         m_jit.store32(lengthGPR, MacroAssembler::Address(resultGPR, JSFixedArray::offsetOfSize()));
 
         m_jit.loadPtr(MacroAssembler::Address(argument, JSObject::butterflyOffset()), scratch1GPR);
@@ -7266,17 +7267,17 @@ void SpeculativeJIT::compileArraySlice(Node* node)
         // to ensure the incoming array is one to be one of the original array structures
         // with one of the following indexing shapes: Int32, Contiguous, Double. Therefore,
         // we're a double array here.
-        m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithDouble)), tempValue);
+        m_jit.move(TrustedImmPtr(m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithDouble))), tempValue);
         emitMoveEmptyValue(jsNaN());
         done.append(m_jit.jump());
 
         isContiguous.link(&m_jit);
-        m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous)), tempValue);
+        m_jit.move(TrustedImmPtr(m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous))), tempValue);
         emitMoveEmptyValue(JSValue());
         done.append(m_jit.jump());
 
         isInt32.link(&m_jit);
-        m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithInt32)), tempValue);
+        m_jit.move(TrustedImmPtr(m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithInt32))), tempValue);
         emitMoveEmptyValue(JSValue());
 
         done.link(&m_jit);
@@ -7456,7 +7457,7 @@ void SpeculativeJIT::compileTypeOf(Node* node)
     m_jit.emitTypeOf(
         valueRegs, resultGPR,
         [&] (TypeofType type, bool fallsThrough) {
-            m_jit.move(TrustedImmPtr(m_jit.vm()->smallStrings.typeString(type)), resultGPR);
+            m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.vm()->smallStrings.typeString(type)), resultGPR);
             if (!fallsThrough)
                 done.append(m_jit.jump());
         },
@@ -7580,7 +7581,7 @@ void SpeculativeJIT::compileAllocatePropertyStorage(Node* node)
     GPRReg scratchGPR2 = scratch2.gpr();
     GPRReg scratchGPR3 = scratch3.gpr();
         
-    m_jit.move(JITCompiler::TrustedImmPtr(allocator), scratchGPR2);
+    m_jit.move(TrustedImmPtr(allocator), scratchGPR2);
     JITCompiler::JumpList slowPath;
     m_jit.emitAllocate(scratchGPR1, allocator, scratchGPR2, scratchGPR3, slowPath);
     m_jit.addPtr(JITCompiler::TrustedImm32(size + sizeof(IndexingHeader)), scratchGPR1);
@@ -7628,7 +7629,7 @@ void SpeculativeJIT::compileReallocatePropertyStorage(Node* node)
     GPRReg scratchGPR3 = scratch3.gpr();
     
     JITCompiler::JumpList slowPath;
-    m_jit.move(JITCompiler::TrustedImmPtr(allocator), scratchGPR2);
+    m_jit.move(TrustedImmPtr(allocator), scratchGPR2);
     m_jit.emitAllocate(scratchGPR1, allocator, scratchGPR2, scratchGPR3, slowPath);
     
     m_jit.addPtr(JITCompiler::TrustedImm32(newSize + sizeof(IndexingHeader)), scratchGPR1);
@@ -7857,10 +7858,10 @@ void SpeculativeJIT::compileToStringOrCallStringConstructorOnCell(Node* node)
         GPRReg resultGPR = result.gpr();
 
         m_jit.load32(JITCompiler::Address(op1GPR, JSCell::structureIDOffset()), resultGPR);
-        JITCompiler::Jump isString = m_jit.branchStructure(
+        JITCompiler::Jump isString = m_jit.branchWeakStructure(
             JITCompiler::Equal,
             resultGPR,
-            m_jit.vm()->stringStructure.get());
+            m_jit.graph().registerStructure(m_jit.vm()->stringStructure.get()));
 
         speculateStringObjectForStructure(node->child1(), resultGPR);
         
@@ -7956,8 +7957,8 @@ void SpeculativeJIT::compileNewTypedArray(Node* node)
 {
     JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
     TypedArrayType type = node->typedArrayType();
-    Structure* structure = globalObject->typedArrayStructureConcurrently(type);
-    RELEASE_ASSERT(structure);
+    RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->typedArrayStructureConcurrently(type));
+    RELEASE_ASSERT(structure.get());
     
     SpeculateInt32Operand size(this, node->child1());
     GPRReg sizeGPR = size.gpr();
@@ -8401,10 +8402,10 @@ void SpeculativeJIT::speculateStringOrStringObject(Edge edge)
     GPRReg structureIDGPR = structureID.gpr();
 
     m_jit.load32(JITCompiler::Address(gpr, JSCell::structureIDOffset()), structureIDGPR); 
-    JITCompiler::Jump isString = m_jit.branchStructure(
+    JITCompiler::Jump isString = m_jit.branchWeakStructure(
         JITCompiler::Equal,
         structureIDGPR, 
-        m_jit.vm()->stringStructure.get());
+        m_jit.graph().registerStructure(m_jit.vm()->stringStructure.get()));
     
     speculateStringObjectForStructure(edge, structureIDGPR);
     
@@ -9267,8 +9268,8 @@ void SpeculativeJIT::compileLazyJSConstant(Node* node)
 
 void SpeculativeJIT::compileMaterializeNewObject(Node* node)
 {
-    Structure* structure = node->structureSet()[0];
-    ASSERT(m_jit.graph().varArgChild(node, 0)->dynamicCastConstant<Structure*>() == structure);
+    RegisteredStructure structure = node->structureSet().at(0);
+    ASSERT(m_jit.graph().varArgChild(node, 0)->dynamicCastConstant<Structure*>() == structure.get());
 
     ObjectMaterializationData& data = node->objectMaterializationData();
         
index 26957d8..45d92d2 100644 (file)
@@ -75,7 +75,6 @@ class SpeculativeJIT {
 private:
     typedef JITCompiler::TrustedImm32 TrustedImm32;
     typedef JITCompiler::Imm32 Imm32;
-    typedef JITCompiler::TrustedImmPtr TrustedImmPtr;
     typedef JITCompiler::ImmPtr ImmPtr;
     typedef JITCompiler::TrustedImm64 TrustedImm64;
     typedef JITCompiler::Imm64 Imm64;
@@ -112,6 +111,64 @@ public:
     SpeculativeJIT(JITCompiler&);
     ~SpeculativeJIT();
 
+    struct TrustedImmPtr {
+        template <typename T>
+        explicit TrustedImmPtr(T* value)
+            : m_value(value)
+        {
+            static_assert(!std::is_base_of<HeapCell, T>::value, "To use a GC pointer, the graph must be aware of it. Use SpeculativeJIT::TrustedImmPtr::weakPointer instead.");
+        }
+
+        explicit TrustedImmPtr(RegisteredStructure structure)
+            : m_value(structure.get())
+        { }
+        
+        // This is only here so that TrustedImmPtr(0) does not confuse the C++
+        // overload handling rules.
+        explicit TrustedImmPtr(int value)
+            : m_value(value)
+        {
+            ASSERT(!value);
+        }
+
+        explicit TrustedImmPtr(std::nullptr_t)
+            : m_value(0)
+        { }
+
+        explicit TrustedImmPtr(FrozenValue* value)
+        {
+            RELEASE_ASSERT(value->value().isCell());
+            m_value = MacroAssembler::TrustedImmPtr(value->cell());
+        }
+
+        explicit TrustedImmPtr(size_t value)
+            : m_value(bitwise_cast<void*>(value))
+        {
+        }
+
+        static TrustedImmPtr weakPointer(Graph& graph, JSCell* cell)
+        {     
+            // There are weird relationships in how optimized CodeBlocks
+            // point to other CodeBlocks. We don't want to have them be
+            // part of the weak pointer set. For example, an optimized CodeBlock
+            // having a weak pointer to itself will cause it to get collected.
+            ASSERT(!jsDynamicCast<CodeBlock*>(cell));
+
+            graph.m_plan.weakReferences.addLazily(cell);
+            return TrustedImmPtr(bitwise_cast<size_t>(cell));
+        }
+
+        operator MacroAssembler::TrustedImmPtr() const { return m_value; }
+
+        intptr_t asIntptr()
+        {
+            return m_value.asIntptr();
+        }
+
+    private:
+        MacroAssembler::TrustedImmPtr m_value;
+    };
+
     bool compile();
     
     void createOSREntries();
@@ -982,17 +1039,17 @@ public:
         m_jit.setupArgumentsWithExecState(obj, impl);
         return appendCallSetResult(operation, result);
     }
-    JITCompiler::Call callOperation(P_JITOperation_ESt operation, GPRReg result, Structure* structure)
+    JITCompiler::Call callOperation(P_JITOperation_ESt operation, GPRReg result, RegisteredStructure structure)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure));
         return appendCallSetResult(operation, result);
     }
-    JITCompiler::Call callOperation(P_JITOperation_EStZP operation, GPRReg result, Structure* structure, GPRReg arg2, GPRReg arg3)
+    JITCompiler::Call callOperation(P_JITOperation_EStZP operation, GPRReg result, RegisteredStructure structure, GPRReg arg2, GPRReg arg3)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), arg2, arg3);
         return appendCallSetResult(operation, result);
     }
-    JITCompiler::Call callOperation(P_JITOperation_EStZP operation, GPRReg result, Structure* structure, size_t arg2, GPRReg arg3)
+    JITCompiler::Call callOperation(P_JITOperation_EStZP operation, GPRReg result, RegisteredStructure structure, size_t arg2, GPRReg arg3)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), TrustedImm32(arg2), arg3);
         return appendCallSetResult(operation, result);
@@ -1002,12 +1059,12 @@ public:
         m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
         return appendCallSetResult(operation, result);
     }
-    JITCompiler::Call callOperation(P_JITOperation_EStZB operation, GPRReg result, Structure* structure, GPRReg arg2, GPRReg butterfly)
+    JITCompiler::Call callOperation(P_JITOperation_EStZB operation, GPRReg result, RegisteredStructure structure, GPRReg arg2, GPRReg butterfly)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), arg2, butterfly);
         return appendCallSetResult(operation, result);
     }
-    JITCompiler::Call callOperation(P_JITOperation_EStZB operation, GPRReg result, Structure* structure, size_t arg2, GPRReg butterfly)
+    JITCompiler::Call callOperation(P_JITOperation_EStZB operation, GPRReg result, RegisteredStructure structure, size_t arg2, GPRReg butterfly)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), TrustedImm32(arg2), butterfly);
         return appendCallSetResult(operation, result);
@@ -1022,12 +1079,12 @@ public:
         m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(butterfly));
         return appendCallSetResult(operation, result);
     }
-    JITCompiler::Call callOperation(P_JITOperation_EStPS operation, GPRReg result, Structure* structure, void* pointer, size_t size)
+    JITCompiler::Call callOperation(P_JITOperation_EStPS operation, GPRReg result, RegisteredStructure structure, void* pointer, size_t size)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), TrustedImmPtr(pointer), TrustedImmPtr(size));
         return appendCallSetResult(operation, result);
     }
-    JITCompiler::Call callOperation(P_JITOperation_EStSS operation, GPRReg result, Structure* structure, size_t index, size_t size)
+    JITCompiler::Call callOperation(P_JITOperation_EStSS operation, GPRReg result, RegisteredStructure structure, size_t index, size_t size)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), TrustedImmPtr(index), TrustedImmPtr(size));
         return appendCallSetResult(operation, result);
@@ -1044,7 +1101,7 @@ public:
     }
     JITCompiler::Call callOperation(C_JITOperation_EC operation, GPRReg result, JSCell* cell)
     {
-        m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell));
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr::weakPointer(m_jit.graph(), cell));
         return appendCallSetResult(operation, result);
     }
     JITCompiler::Call callOperation(C_JITOperation_ECZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
@@ -1059,7 +1116,7 @@ public:
     }
     JITCompiler::Call callOperation(C_JITOperation_EJscC operation, GPRReg result, GPRReg arg1, JSCell* cell)
     {
-        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell));
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr::weakPointer(m_jit.graph(), cell));
         return appendCallSetResult(operation, result);
     }
     JITCompiler::Call callOperation(C_JITOperation_EIcf operation, GPRReg result, InlineCallFrame* inlineCallFrame)
@@ -1067,46 +1124,46 @@ public:
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(inlineCallFrame));
         return appendCallSetResult(operation, result);
     }
-    JITCompiler::Call callOperation(C_JITOperation_ESt operation, GPRReg result, Structure* structure)
+    JITCompiler::Call callOperation(C_JITOperation_ESt operation, GPRReg result, RegisteredStructure structure)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure));
         return appendCallSetResult(operation, result);
     }
 
 #if USE(JSVALUE64)
-    JITCompiler::Call callOperation(C_JITOperation_EStJscSymtabJ operation, GPRReg result, Structure* structure, GPRReg scope, SymbolTable* table, TrustedImm64 initialValue)
+    JITCompiler::Call callOperation(C_JITOperation_EStJscSymtabJ operation, GPRReg result, RegisteredStructure structure, GPRReg scope, SymbolTable* table, TrustedImm64 initialValue)
     {
-        m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), scope, TrustedImmPtr(table), initialValue);
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), scope, TrustedImmPtr::weakPointer(m_jit.graph(), table), initialValue);
         return appendCallSetResult(operation, result);
     }
 #else
-    JITCompiler::Call callOperation(C_JITOperation_EStJscSymtabJ operation, GPRReg result, Structure* structure, GPRReg scope, SymbolTable* table, TrustedImm32 tag, TrustedImm32 payload)
+    JITCompiler::Call callOperation(C_JITOperation_EStJscSymtabJ operation, GPRReg result, RegisteredStructure structure, GPRReg scope, SymbolTable* table, TrustedImm32 tag, TrustedImm32 payload)
     {
-        m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), scope, TrustedImmPtr(table), payload, tag);
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), scope, TrustedImmPtr::weakPointer(m_jit.graph(), table), payload, tag);
         return appendCallSetResult(operation, result);
     }
 #endif
-    JITCompiler::Call callOperation(C_JITOperation_EStZ operation, GPRReg result, Structure* structure, unsigned knownLength)
+    JITCompiler::Call callOperation(C_JITOperation_EStZ operation, GPRReg result, RegisteredStructure structure, unsigned knownLength)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), TrustedImm32(knownLength));
         return appendCallSetResult(operation, result);
     }
-    JITCompiler::Call callOperation(C_JITOperation_EStZZ operation, GPRReg result, Structure* structure, unsigned knownLength, unsigned minCapacity)
+    JITCompiler::Call callOperation(C_JITOperation_EStZZ operation, GPRReg result, RegisteredStructure structure, unsigned knownLength, unsigned minCapacity)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), TrustedImm32(knownLength), TrustedImm32(minCapacity));
         return appendCallSetResult(operation, result);
     }
-    JITCompiler::Call callOperation(C_JITOperation_EStZ operation, GPRReg result, Structure* structure, GPRReg length)
+    JITCompiler::Call callOperation(C_JITOperation_EStZ operation, GPRReg result, RegisteredStructure structure, GPRReg length)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), length);
         return appendCallSetResult(operation, result);
     }
-    JITCompiler::Call callOperation(C_JITOperation_EStZZ operation, GPRReg result, Structure* structure, GPRReg length, unsigned minCapacity)
+    JITCompiler::Call callOperation(C_JITOperation_EStZZ operation, GPRReg result, RegisteredStructure structure, GPRReg length, unsigned minCapacity)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), length, TrustedImm32(minCapacity));
         return appendCallSetResult(operation, result);
     }
-    JITCompiler::Call callOperation(C_JITOperation_EJssSt operation, GPRReg result, GPRReg arg1, Structure* structure)
+    JITCompiler::Call callOperation(C_JITOperation_EJssSt operation, GPRReg result, GPRReg arg1, RegisteredStructure structure)
     {
         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(structure));
         return appendCallSetResult(operation, result);
@@ -1140,13 +1197,13 @@ public:
 
     JITCompiler::Call callOperation(S_JITOperation_EGC operation, GPRReg result, JSGlobalObject* globalObject, GPRReg arg2)
     {
-        m_jit.setupArgumentsWithExecState(TrustedImmPtr(globalObject), arg2);
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr::weakPointer(m_jit.graph(), globalObject), arg2);
         return appendCallSetResult(operation, result);
     }
 
     JITCompiler::Call callOperation(C_JITOperation_EGC operation, GPRReg result, JSGlobalObject* globalObject, GPRReg arg2)
     {
-        m_jit.setupArgumentsWithExecState(TrustedImmPtr(globalObject), arg2);
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr::weakPointer(m_jit.graph(), globalObject), arg2);
         return appendCallSetResult(operation, result);
     }
 
@@ -1170,7 +1227,7 @@ public:
 
     JITCompiler::Call callOperation(V_JITOperation_EC operation, JSCell* arg1)
     {
-        m_jit.setupArgumentsWithExecState(TrustedImmPtr(arg1));
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr::weakPointer(m_jit.graph(), arg1));
         return appendCall(operation);
     }
 
@@ -1197,12 +1254,12 @@ public:
     }
     JITCompiler::Call callOperation(V_JITOperation_ECC operation, GPRReg arg1, JSCell* arg2)
     {
-        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(arg2));
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr::weakPointer(m_jit.graph(), arg2));
         return appendCall(operation);
     }
     JITCompiler::Call callOperation(V_JITOperation_ECC operation, JSCell* arg1, GPRReg arg2)
     {
-        m_jit.setupArgumentsWithExecState(TrustedImmPtr(arg1), arg2);
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr::weakPointer(m_jit.graph(), arg1), arg2);
         return appendCall(operation);
     }
 
@@ -1273,13 +1330,13 @@ public:
 
     JITCompiler::Call callOperation(J_JITOperation_EJscC operation, GPRReg result, GPRReg arg1, JSCell* cell)
     {
-        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell));
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr::weakPointer(m_jit.graph(), cell));
         return appendCallSetResult(operation, result);
     }
     
     JITCompiler::Call callOperation(J_JITOperation_EJscCJ operation, GPRReg result, GPRReg arg1, JSCell* cell, GPRReg arg2)
     {
-        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell), arg2);
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr::weakPointer(m_jit.graph(), cell), arg2);
         return appendCallSetResult(operation, result);
     }
 
@@ -1474,7 +1531,7 @@ public:
     }
     JITCompiler::Call callOperation(J_JITOperation_EC operation, GPRReg result, JSCell* cell)
     {
-        m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell));
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr::weakPointer(m_jit.graph(), cell));
         return appendCallSetResult(operation, result);
     }
     JITCompiler::Call callOperation(J_JITOperation_ECZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
@@ -1544,7 +1601,7 @@ public:
         return appendCallSetResult(operation, result);
     }
 
-    JITCompiler::Call callOperation(P_JITOperation_EStJ operation, GPRReg result, Structure* structure, GPRReg arg2)
+    JITCompiler::Call callOperation(P_JITOperation_EStJ operation, GPRReg result, RegisteredStructure structure, GPRReg arg2)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), arg2);
         return appendCallSetResult(operation, result);
@@ -1552,7 +1609,7 @@ public:
 
     JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, JSGlobalObject* globalObject, GPRReg arg1)
     {
-        m_jit.setupArgumentsWithExecState(TrustedImmPtr(globalObject), arg1);
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr::weakPointer(m_jit.graph(), globalObject), arg1);
         return appendCallSetResult(operation, result);
     }
 
@@ -1900,7 +1957,7 @@ public:
     }
     JITCompiler::Call callOperation(D_JITOperation_G operation, FPRReg result, JSGlobalObject* globalObject)
     {
-        m_jit.setupArguments(TrustedImmPtr(globalObject));
+        m_jit.setupArguments(TrustedImmPtr::weakPointer(m_jit.graph(), globalObject));
         return appendCallSetResult(operation, result);
     }
     JITCompiler::Call callOperation(Z_JITOperation_D operation, GPRReg result, FPRReg arg1)
@@ -2009,7 +2066,7 @@ public:
 
     JITCompiler::Call callOperation(J_JITOperation_EC operation, JSValueRegs result, JSCell* cell)
     {
-        m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell));
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr::weakPointer(m_jit.graph(), cell));
         return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
     }
     JITCompiler::Call callOperation(J_JITOperation_ECZ operation, JSValueRegs result, GPRReg arg1, GPRReg arg2)
@@ -2019,12 +2076,12 @@ public:
     }
     JITCompiler::Call callOperation(J_JITOperation_EJscC operation, JSValueRegs result, GPRReg arg1, JSCell* cell)
     {
-        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell));
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr::weakPointer(m_jit.graph(), cell));
         return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
     }
     JITCompiler::Call callOperation(J_JITOperation_EJscCJ operation, GPRReg result, GPRReg arg1, JSCell* cell, JSValueRegs arg2)
     {
-        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell), EABI_32BIT_DUMMY_ARG arg2.payloadGPR(), arg2.tagGPR());
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr::weakPointer(m_jit.graph(), cell), EABI_32BIT_DUMMY_ARG arg2.payloadGPR(), arg2.tagGPR());
         return appendCallSetResult(operation, result);
     }
     JITCompiler::Call callOperation(J_JITOperation_EGReoJ operation, JSValueRegs result, GPRReg arg1, GPRReg arg2, JSValueRegs arg3)
@@ -2109,7 +2166,7 @@ public:
         return appendCallSetResult(operation, result);
     }
 
-    JITCompiler::Call callOperation(P_JITOperation_EStJ operation, GPRReg result, Structure* structure, JSValueRegs arg2)
+    JITCompiler::Call callOperation(P_JITOperation_EStJ operation, GPRReg result, RegisteredStructure structure, JSValueRegs arg2)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), arg2.payloadGPR(), arg2.tagGPR());
         return appendCallSetResult(operation, result);
@@ -2117,7 +2174,7 @@ public:
 
     JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, JSGlobalObject* globalObject, JSValueRegs arg1)
     {
-        m_jit.setupArgumentsWithExecState(TrustedImmPtr(globalObject), arg1.payloadGPR(), arg1.tagGPR());
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr::weakPointer(m_jit.graph(), globalObject), arg1.payloadGPR(), arg1.tagGPR());
         return appendCallSetResult(operation, result);
     }
 
@@ -2667,7 +2724,7 @@ public:
     void compilePutByValForIntTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType);
     void compileGetByValOnFloatTypedArray(Node*, TypedArrayType);
     void compilePutByValForFloatTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType);
-    template <typename ClassType> void compileNewFunctionCommon(GPRReg, Structure*, GPRReg, GPRReg, GPRReg, MacroAssembler::JumpList&, size_t, FunctionExecutable*, ptrdiff_t, ptrdiff_t, ptrdiff_t);
+    template <typename ClassType> void compileNewFunctionCommon(GPRReg, RegisteredStructure, GPRReg, GPRReg, GPRReg, MacroAssembler::JumpList&, size_t, FunctionExecutable*, ptrdiff_t, ptrdiff_t, ptrdiff_t);
     void compileNewFunction(Node*);
     void compileSetFunctionName(Node*);
     void compileForwardVarargs(Node*);
@@ -2753,13 +2810,13 @@ public:
     }
 
     template<typename ClassType>
-    void emitAllocateDestructibleObject(GPRReg resultGPR, Structure* structure, 
+    void emitAllocateDestructibleObject(GPRReg resultGPR, RegisteredStructure structure, 
         GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath)
     {
-        m_jit.emitAllocateDestructibleObject<ClassType>(resultGPR, structure, scratchGPR1, scratchGPR2, slowPath);
+        m_jit.emitAllocateDestructibleObject<ClassType>(resultGPR, structure.get(), scratchGPR1, scratchGPR2, slowPath);
     }
 
-    void emitAllocateRawObject(GPRReg resultGPR, Structure*, GPRReg storageGPR, unsigned numElements, unsigned vectorLength);
+    void emitAllocateRawObject(GPRReg resultGPR, RegisteredStructure, GPRReg storageGPR, unsigned numElements, unsigned vectorLength);
     
     void emitGetLength(InlineCallFrame*, GPRReg lengthGPR, bool includeThis = false);
     void emitGetLength(CodeOrigin, GPRReg lengthGPR, bool includeThis = false);
@@ -3774,13 +3831,13 @@ private:
 template<typename StructureLocationType>
 void SpeculativeJIT::speculateStringObjectForStructure(Edge edge, StructureLocationType structureLocation)
 {
-    Structure* stringObjectStructure =
-        m_jit.globalObjectFor(m_currentNode->origin.semantic)->stringObjectStructure();
+    RegisteredStructure stringObjectStructure =
+        m_jit.graph().registerStructure(m_jit.globalObjectFor(m_currentNode->origin.semantic)->stringObjectStructure());
     
-    if (!m_state.forNode(edge).m_structure.isSubsetOf(StructureSet(stringObjectStructure))) {
+    if (!m_state.forNode(edge).m_structure.isSubsetOf(RegisteredStructureSet(stringObjectStructure))) {
         speculationCheck(
             NotStringObject, JSValueRegs(), 0,
-            m_jit.branchStructure(
+            m_jit.branchWeakStructure(
                 JITCompiler::NotEqual, structureLocation, stringObjectStructure));
     }
 }
index ab09229..e3fc88e 100644 (file)
@@ -294,7 +294,7 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operan
         isMasqueradesAsUndefined.link(&m_jit);
         GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
         GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
-        m_jit.move(JITCompiler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
+        m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
         m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureIDOffset()), resultPayloadGPR);
         m_jit.loadPtr(JITCompiler::Address(resultPayloadGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
         m_jit.compare32(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, resultPayloadGPR);
@@ -358,7 +358,7 @@ void SpeculativeJIT::nonSpeculativePeepholeBranchNullOrUndefined(Edge operand, N
    
         GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
         GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
-        m_jit.move(TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
+        m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
         m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureIDOffset()), resultGPR);
         m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
         branchPtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, invert ? notTaken : taken);
@@ -1082,7 +1082,7 @@ void SpeculativeJIT::emitCall(Node* node)
             m_jit.emitRestoreCalleeSaves();
     }
 
-    m_jit.move(MacroAssembler::TrustedImmPtr(info), GPRInfo::regT2);
+    m_jit.move(TrustedImmPtr(info), GPRInfo::regT2);
     JITCompiler::Call slowCall = m_jit.nearCall();
 
     done.link(&m_jit);
@@ -1242,10 +1242,9 @@ GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
     switch (info.registerFormat()) {
     case DataFormatNone: {
         if (edge->hasConstant()) {
-            JSValue jsValue = edge->asJSValue();
             GPRReg gpr = allocate();
             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
-            m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
+            m_jit.move(TrustedImmPtr(edge->constant()), gpr);
             info.fillCell(*m_stream, gpr);
             return gpr;
         }
@@ -1724,7 +1723,7 @@ void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse)
             m_jit.branchPtr(
                 MacroAssembler::Equal, 
                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
-                MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
+                TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
 
         isNotMasqueradesAsUndefined.link(&m_jit);
     }
@@ -1843,7 +1842,7 @@ void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BasicBlock* taken, Ba
             m_jit.branchPtr(
                 MacroAssembler::Equal, 
                 MacroAssembler::Address(scratchGPR, Structure::globalObjectOffset()), 
-                MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
+                TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
 
         isNotMasqueradesAsUndefined.link(&m_jit);
     }
@@ -3778,7 +3777,7 @@ void SpeculativeJIT::compile(Node* node)
     case NewArray: {
         JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
         if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(node->indexingType())) {
-            Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType());
+            RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
             ASSERT(structure->indexingType() == node->indexingType());
             ASSERT(
                 hasUndecided(structure->indexingType())
@@ -3853,7 +3852,7 @@ void SpeculativeJIT::compile(Node* node)
             flushRegisters();
             GPRFlushedCallResult result(this);
             callOperation(
-                operationNewEmptyArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
+                operationNewEmptyArray, result.gpr(), m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())));
             m_jit.exceptionCheck();
             cellResult(result.gpr(), node);
             break;
@@ -3930,7 +3929,7 @@ void SpeculativeJIT::compile(Node* node)
         GPRFlushedCallResult result(this);
         
         callOperation(
-            operationNewArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()),
+            operationNewArray, result.gpr(), m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())),
             static_cast<void*>(buffer), node->numChildren());
         m_jit.exceptionCheck();
 
@@ -3976,10 +3975,10 @@ void SpeculativeJIT::compile(Node* node)
         GPRReg resultGPR = result.gpr();
         GPRReg structureGPR = selectScratchGPR(sizeGPR);
         MacroAssembler::Jump bigLength = m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH));
-        m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())), structureGPR);
+        m_jit.move(TrustedImmPtr(m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()))), structureGPR);
         MacroAssembler::Jump done = m_jit.jump();
         bigLength.link(&m_jit);
-        m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)), structureGPR);
+        m_jit.move(TrustedImmPtr(m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage))), structureGPR);
         done.link(&m_jit);
         callOperation(operationNewArrayWithSize, resultGPR, structureGPR, sizeGPR, nullptr);
         m_jit.exceptionCheck();
@@ -3999,7 +3998,7 @@ void SpeculativeJIT::compile(Node* node)
             GPRReg resultGPR = result.gpr();
             GPRReg storageGPR = storage.gpr();
 
-            emitAllocateRawObject(resultGPR, globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements, numElements);
+            emitAllocateRawObject(resultGPR, m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType)), storageGPR, numElements, numElements);
             
             if (node->indexingType() == ArrayWithDouble) {
                 JSValue* data = m_jit.codeBlock()->constantBuffer(node->startConstant());
@@ -4027,7 +4026,7 @@ void SpeculativeJIT::compile(Node* node)
         flushRegisters();
         GPRFlushedCallResult result(this);
         
-        callOperation(operationNewArrayBuffer, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()), node->startConstant(), node->numConstants());
+        callOperation(operationNewArrayBuffer, result.gpr(), m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())), node->startConstant(), node->numConstants());
         m_jit.exceptionCheck();
         
         cellResult(result.gpr(), node);
@@ -4051,7 +4050,7 @@ void SpeculativeJIT::compile(Node* node)
             JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
             callOperation(
                 operationNewTypedArrayWithOneArgumentForType(node->typedArrayType()),
-                resultGPR, globalObject->typedArrayStructureConcurrently(node->typedArrayType()), argumentRegs);
+                resultGPR, m_jit.graph().registerStructure(globalObject->typedArrayStructureConcurrently(node->typedArrayType())), argumentRegs);
             m_jit.exceptionCheck();
             
             cellResult(resultGPR, node);
@@ -4171,7 +4170,7 @@ void SpeculativeJIT::compile(Node* node)
         
         MacroAssembler::JumpList slowPath;
         
-        Structure* structure = node->structure();
+        RegisteredStructure structure = node->structure();
         size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
         MarkedAllocator* allocatorPtr = subspaceFor<JSFinalObject>(*m_jit.vm())->allocatorFor(allocationSize);
 
@@ -4416,8 +4415,8 @@ void SpeculativeJIT::compile(Node* node)
     }
         
     case PutStructure: {
-        Structure* oldStructure = node->transition()->previous;
-        Structure* newStructure = node->transition()->next;
+        RegisteredStructure oldStructure = node->transition()->previous;
+        RegisteredStructure newStructure = node->transition()->next;
 
         m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node);
 
@@ -4427,7 +4426,7 @@ void SpeculativeJIT::compile(Node* node)
         ASSERT_UNUSED(oldStructure, oldStructure->indexingType() == newStructure->indexingType());
         ASSERT(oldStructure->typeInfo().type() == newStructure->typeInfo().type());
         ASSERT(oldStructure->typeInfo().inlineTypeFlags() == newStructure->typeInfo().inlineTypeFlags());
-        m_jit.storePtr(MacroAssembler::TrustedImmPtr(newStructure), MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()));
+        m_jit.storePtr(TrustedImmPtr(newStructure), MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()));
         
         noResult(node);
         break;
@@ -4691,7 +4690,7 @@ void SpeculativeJIT::compile(Node* node)
         if (!hasInstanceValueNode->isCellConstant() || defaultHasInstanceFunction != hasInstanceValueNode->asCell()) {
             JSValueRegs hasInstanceValueRegs = hasInstanceValue.jsValueRegs();
             notDefaultHasInstanceValue.append(m_jit.branchIfNotCell(hasInstanceValueRegs));
-            notDefaultHasInstanceValue.append(m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValueRegs.payloadGPR(), TrustedImmPtr(defaultHasInstanceFunction)));
+            notDefaultHasInstanceValue.append(m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValueRegs.payloadGPR(), TrustedImmPtr(node->cellOperand())));
         }
 
         // Check that constructor 'ImplementsDefaultHasInstance'.
@@ -4753,7 +4752,7 @@ void SpeculativeJIT::compile(Node* node)
             isMasqueradesAsUndefined.link(&m_jit);
             GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
             GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
-            m_jit.move(TrustedImmPtr(m_jit.globalObjectFor(node->origin.semantic)), localGlobalObjectGPR);
+            m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.globalObjectFor(node->origin.semantic)), localGlobalObjectGPR);
             m_jit.loadPtr(JITCompiler::Address(value.payloadGPR(), JSCell::structureIDOffset()), result.gpr());
             m_jit.loadPtr(JITCompiler::Address(result.gpr(), Structure::globalObjectOffset()), remoteGlobalObjectGPR); 
             m_jit.compare32(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, result.gpr());
@@ -5713,13 +5712,13 @@ void SpeculativeJIT::compileAllocateNewArrayWithSize(JSGlobalObject* globalObjec
     // We can use result as a scratch for this.
     emitInitializeButterfly(storageGPR, sizeGPR, emptyValueRegs, resultGPR);
             
-    Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType);
+    RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType));
     emitAllocateJSObject<JSArray>(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
             
     addSlowPathGenerator(std::make_unique<CallArrayAllocatorWithVariableSizeSlowPathGenerator>(
         slowCases, this, operationNewArrayWithSize, resultGPR,
         structure,
-        shouldConvertLargeSizeToArrayStorage ? globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage) : structure,
+        shouldConvertLargeSizeToArrayStorage ? m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)) : structure,
         sizeGPR, storageGPR));
 }
 
index 3f098de..94c8cdb 100644 (file)
@@ -250,7 +250,7 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operan
 
         GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
         GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
-        m_jit.move(JITCompiler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
+        m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
         m_jit.emitLoadStructure(argGPR, resultGPR, scratch.gpr());
         m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
         m_jit.comparePtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, resultGPR);
@@ -305,7 +305,7 @@ void SpeculativeJIT::nonSpeculativePeepholeBranchNullOrUndefined(Edge operand, N
 
         GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
         GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
-        m_jit.move(TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
+        m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
         m_jit.emitLoadStructure(argGPR, resultGPR, scratch.gpr());
         m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
         branchPtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, taken);
@@ -1006,7 +1006,7 @@ void SpeculativeJIT::emitCall(Node* node)
     m_jit.emitStoreCallSiteIndex(callSite);
     
     JITCompiler::DataLabelPtr targetToCheck;
-    JITCompiler::Jump slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(0));
+    JITCompiler::Jump slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, TrustedImmPtr(0));
 
     if (isTail) {
         if (node->op() == TailCall) {
@@ -1035,7 +1035,7 @@ void SpeculativeJIT::emitCall(Node* node)
             m_jit.emitRestoreCalleeSaves(); // This needs to happen after we moved calleeGPR to regT0
     }
 
-    m_jit.move(MacroAssembler::TrustedImmPtr(callLinkInfo), GPRInfo::regT2); // Link info needs to be in regT2
+    m_jit.move(TrustedImmPtr(callLinkInfo), GPRInfo::regT2); // Link info needs to be in regT2
     JITCompiler::Call slowCall = m_jit.nearCall();
 
     done.link(&m_jit);
@@ -1856,7 +1856,7 @@ void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse)
             m_jit.branchPtr(
                 MacroAssembler::Equal, 
                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
-                MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
+                TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
 
         isNotMasqueradesAsUndefined.link(&m_jit);
     }
@@ -2007,7 +2007,7 @@ void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BasicBlock* taken, Ba
             m_jit.branchPtr(
                 MacroAssembler::Equal, 
                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
-                MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
+                TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
 
         isNotMasqueradesAsUndefined.link(&m_jit);
     }
@@ -3757,7 +3757,7 @@ void SpeculativeJIT::compile(Node* node)
     case NewArray: {
         JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
         if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(node->indexingType())) {
-            Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType());
+            RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
             DFG_ASSERT(m_jit.graph(), node, structure->indexingType() == node->indexingType());
             ASSERT(
                 hasUndecided(structure->indexingType())
@@ -3830,7 +3830,7 @@ void SpeculativeJIT::compile(Node* node)
         if (!node->numChildren()) {
             flushRegisters();
             GPRFlushedCallResult result(this);
-            callOperation(operationNewEmptyArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
+            callOperation(operationNewEmptyArray, result.gpr(), m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())));
             m_jit.exceptionCheck();
             cellResult(result.gpr(), node);
             break;
@@ -3912,7 +3912,7 @@ void SpeculativeJIT::compile(Node* node)
         GPRFlushedCallResult result(this);
         
         callOperation(
-            operationNewArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()),
+            operationNewArray, result.gpr(), m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())),
             static_cast<void*>(buffer), node->numChildren());
         m_jit.exceptionCheck();
 
@@ -3956,10 +3956,10 @@ void SpeculativeJIT::compile(Node* node)
         GPRReg resultGPR = result.gpr();
         GPRReg structureGPR = selectScratchGPR(sizeGPR);
         MacroAssembler::Jump bigLength = m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH));
-        m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())), structureGPR);
+        m_jit.move(TrustedImmPtr(m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()))), structureGPR);
         MacroAssembler::Jump done = m_jit.jump();
         bigLength.link(&m_jit);
-        m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)), structureGPR);
+        m_jit.move(TrustedImmPtr(m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage))), structureGPR);
         done.link(&m_jit);
         callOperation(operationNewArrayWithSize, resultGPR, structureGPR, sizeGPR, nullptr);
         m_jit.exceptionCheck();
@@ -3979,7 +3979,7 @@ void SpeculativeJIT::compile(Node* node)
             GPRReg resultGPR = result.gpr();
             GPRReg storageGPR = storage.gpr();
 
-            emitAllocateRawObject(resultGPR, globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements, numElements);
+            emitAllocateRawObject(resultGPR, m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType)), storageGPR, numElements, numElements);
             
             DFG_ASSERT(m_jit.graph(), node, indexingType & IsArray);
             JSValue* data = m_jit.codeBlock()->constantBuffer(node->startConstant());
@@ -4005,7 +4005,7 @@ void SpeculativeJIT::compile(Node* node)
         flushRegisters();
         GPRFlushedCallResult result(this);
         
-        callOperation(operationNewArrayBuffer, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()), node->startConstant(), node->numConstants());
+        callOperation(operationNewArrayBuffer, result.gpr(), m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())), node->startConstant(), node->numConstants());
         m_jit.exceptionCheck();
         
         cellResult(result.gpr(), node);
@@ -4029,7 +4029,7 @@ void SpeculativeJIT::compile(Node* node)
             JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
             callOperation(
                 operationNewTypedArrayWithOneArgumentForType(node->typedArrayType()),
-                resultGPR, globalObject->typedArrayStructureConcurrently(node->typedArrayType()),
+                resultGPR, m_jit.graph().registerStructure(globalObject->typedArrayStructureConcurrently(node->typedArrayType())),
                 argumentGPR);
             m_jit.exceptionCheck();
             
@@ -4143,7 +4143,7 @@ void SpeculativeJIT::compile(Node* node)
         
         MacroAssembler::JumpList slowPath;
 
-        Structure* structure = node->structure();
+        RegisteredStructure structure = node->structure();
         size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
         MarkedAllocator* allocatorPtr = subspaceFor<JSFinalObject>(*m_jit.vm())->allocatorFor(allocationSize);
 
@@ -4376,8 +4376,8 @@ void SpeculativeJIT::compile(Node* node)
     }
         
     case PutStructure: {
-        Structure* oldStructure = node->transition()->previous;
-        Structure* newStructure = node->transition()->next;
+        RegisteredStructure oldStructure = node->transition()->previous;
+        RegisteredStructure newStructure = node->transition()->next;
 
         m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node);
 
@@ -4652,7 +4652,7 @@ void SpeculativeJIT::compile(Node* node)
         // since it relies on OSR information. https://bugs.webkit.org/show_bug.cgi?id=154832
         if (!hasInstanceValueNode->isCellConstant() || defaultHasInstanceFunction != hasInstanceValueNode->asCell()) {
             GPRReg hasInstanceValueGPR = hasInstanceValue.gpr();
-            notDefault = m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValueGPR, TrustedImmPtr(defaultHasInstanceFunction));
+            notDefault = m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValueGPR, TrustedImmPtr(node->cellOperand()));
         }
 
         // Check that base 'ImplementsDefaultHasInstance'.
@@ -4719,7 +4719,7 @@ void SpeculativeJIT::compile(Node* node)
             isMasqueradesAsUndefined.link(&m_jit);
             GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
             GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
-            m_jit.move(TrustedImmPtr(m_jit.globalObjectFor(node->origin.semantic)), localGlobalObjectGPR);
+            m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.globalObjectFor(node->origin.semantic)), localGlobalObjectGPR);
             m_jit.emitLoadStructure(value.gpr(), result.gpr(), scratch.gpr());
             m_jit.loadPtr(JITCompiler::Address(result.gpr(), Structure::globalObjectOffset()), remoteGlobalObjectGPR); 
             m_jit.comparePtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, result.gpr());
@@ -4912,9 +4912,9 @@ void SpeculativeJIT::compile(Node* node)
         m_jit.loadPtr(MacroAssembler::BaseIndex(bufferGPR, indexGPR, MacroAssembler::TimesEight), bucketGPR);
         m_jit.move(bucketGPR, resultGPR);
         auto notPresentInTable = m_jit.branchPtr(MacroAssembler::Equal, 
-            bucketGPR, TrustedImmPtr(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::emptyValue()));
+            bucketGPR, TrustedImmPtr(bitwise_cast<size_t>(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::emptyValue())));
         loopAround.append(m_jit.branchPtr(MacroAssembler::Equal, 
-            bucketGPR, TrustedImmPtr(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::deletedValue())));
+            bucketGPR, TrustedImmPtr(bitwise_cast<size_t>(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::deletedValue()))));
 
         m_jit.load64(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKey>::offsetOfKey()), bucketGPR);
 
@@ -5982,7 +5982,7 @@ void SpeculativeJIT::compileAllocateNewArrayWithSize(JSGlobalObject* globalObjec
         m_jit.move(TrustedImm64(JSValue::encode(JSValue())), scratchGPR);
     emitInitializeButterfly(storageGPR, sizeGPR, JSValueRegs(scratchGPR), scratch2GPR);
 
-    Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType);
+    RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType));
     
     emitAllocateJSObject<JSArray>(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
     
@@ -5991,7 +5991,7 @@ void SpeculativeJIT::compileAllocateNewArrayWithSize(JSGlobalObject* globalObjec
     addSlowPathGenerator(std::make_unique<CallArrayAllocatorWithVariableSizeSlowPathGenerator>(
         slowCases, this, operationNewArrayWithSize, resultGPR,
         structure,
-        shouldConvertLargeSizeToArrayStorage ? globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage) : structure,
+        shouldConvertLargeSizeToArrayStorage ? m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)) : structure,
         sizeGPR, storageGPR));
 }
 
index 66c5008..31d8609 100644 (file)
@@ -540,7 +540,7 @@ private:
 
             if (m_node->op() == RegExpExec) {
                 if (result) {
-                    StructureSet* structureSet = m_graph.addStructureSet(structure);
+                    RegisteredStructureSet* structureSet = m_graph.addStructureSet(structure);
 
                     // Create an array modeling the JS array that we will try to allocate. This is
                     // basically createRegExpMatchesArray but over C++ strings instead of JSStrings.
index 88d5775..d9d9c6c 100644 (file)
@@ -39,7 +39,7 @@ void StructureAbstractValue::assertIsRegistered(Graph& graph) const
         return;
     
     for (unsigned i = size(); i--;)
-        graph.assertIsRegistered(at(i));
+        graph.assertIsRegistered(at(i).get());
 }
 #endif // !ASSERT_DISABLED
 
@@ -62,7 +62,7 @@ void StructureAbstractValue::clobber()
         return;
     }
     
-    StructureSet::OutOfLineList* list = m_set.list();
+    RegisteredStructureSet::OutOfLineList* list = m_set.list();
     for (unsigned i = list->m_length; i--;) {
         if (!list->list()[i]->dfgShouldWatch()) {
             makeTop();
@@ -71,7 +71,7 @@ void StructureAbstractValue::clobber()
     }
 }
 
-void StructureAbstractValue::observeTransition(Structure* from, Structure* to)
+void StructureAbstractValue::observeTransition(RegisteredStructure from, RegisteredStructure to)
 {
     ASSERT(!from->dfgShouldWatch());
 
@@ -93,7 +93,7 @@ void StructureAbstractValue::observeTransitions(const TransitionVector& vector)
     if (isTop())
         return;
     
-    StructureSet newStructures;
+    RegisteredStructureSet newStructures;
     for (unsigned i = vector.size(); i--;) {
         ASSERT(!vector[i].previous->dfgShouldWatch());
 
@@ -110,7 +110,7 @@ void StructureAbstractValue::observeTransitions(const TransitionVector& vector)
         makeTop();
 }
 
-bool StructureAbstractValue::add(Structure* structure)
+bool StructureAbstractValue::add(RegisteredStructure structure)
 {
     if (isTop())
         return false;
@@ -124,7 +124,7 @@ bool StructureAbstractValue::add(Structure* structure)
     return true;
 }
 
-bool StructureAbstractValue::merge(const StructureSet& other)
+bool StructureAbstractValue::merge(const RegisteredStructureSet& other)
 {
     if (isTop())
         return false;
@@ -175,7 +175,7 @@ bool StructureAbstractValue::mergeSlow(const StructureAbstractValue& other)
     return changed;
 }
 
-bool StructureAbstractValue::mergeNotTop(const StructureSet& other)
+bool StructureAbstractValue::mergeNotTop(const RegisteredStructureSet& other)
 {
     if (!m_set.merge(other))
         return false;
@@ -186,7 +186,7 @@ bool StructureAbstractValue::mergeNotTop(const StructureSet& other)
     return true;
 }
 
-void StructureAbstractValue::filter(const StructureSet& other)
+void StructureAbstractValue::filter(const RegisteredStructureSet& other)
 {
     if (isTop()) {
         m_set = other;
@@ -229,7 +229,7 @@ void StructureAbstractValue::filter(const StructureAbstractValue& other)
             return;
         
         if (!isClobbered()) {
-            // See justification in filter(const StructureSet&), above. An unclobbered set is
+            // See justification in filter(const RegisteredStructureSet&), above. An unclobbered set is
             // almost always better.
             if (m_set.size() > other.m_set.size() + clobberedSupremacyThreshold)
                 *this = other; // Keep the clobbered set.
@@ -253,8 +253,8 @@ void StructureAbstractValue::filterSlow(SpeculatedType type)
     ASSERT(!isTop());
     
     m_set.genericFilter(
-        [&] (Structure* structure) {
-            return !!(speculationFromStructure(structure) & type);
+        [&] (RegisteredStructure structure) {
+            return !!(speculationFromStructure(structure.get()) & type);
         });
 }
 
@@ -262,12 +262,12 @@ void StructureAbstractValue::filterClassInfoSlow(const ClassInfo* classInfo)
 {
     ASSERT(!isTop());
     m_set.genericFilter(
-        [&] (Structure* structure) {
+        [&] (RegisteredStructure structure) {
             return structure->classInfo()->isSubClassOf(classInfo);
         });
 }
 
-bool StructureAbstractValue::contains(Structure* structure) const
+bool StructureAbstractValue::contains(RegisteredStructure structure) const
 {
     if (isInfinite())
         return true;
@@ -275,7 +275,15 @@ bool StructureAbstractValue::contains(Structure* structure) const
     return m_set.contains(structure);
 }
 
-bool StructureAbstractValue::isSubsetOf(const StructureSet& other) const
+bool StructureAbstractValue::contains(Structure* structure) const
+{
+    if (isInfinite())
+        return true;
+    
+    return m_set.toStructureSet().contains(structure);
+}
+
+bool StructureAbstractValue::isSubsetOf(const RegisteredStructureSet& other) const
 {
     if (isInfinite())
         return false;
@@ -304,7 +312,7 @@ bool StructureAbstractValue::isSubsetOf(const StructureAbstractValue& other) con
     return m_set.isSubsetOf(other.m_set);
 }
 
-bool StructureAbstractValue::isSupersetOf(const StructureSet& other) const
+bool StructureAbstractValue::isSupersetOf(const RegisteredStructureSet& other) const
 {
     if (isInfinite())
         return true;
@@ -312,7 +320,7 @@ bool StructureAbstractValue::isSupersetOf(const StructureSet& other) const
     return m_set.isSupersetOf(other);
 }
 
-bool StructureAbstractValue::overlaps(const StructureSet& other) const
+bool StructureAbstractValue::overlaps(const RegisteredStructureSet& other) const
 {
     if (isInfinite())
         return true;
@@ -334,7 +342,7 @@ bool StructureAbstractValue::isSubClassOf(const ClassInfo* classInfo) const
         return false;
 
     // Note taht this function returns true if the structure set is empty.
-    for (const Structure* structure : m_set) {
+    for (const RegisteredStructure structure : m_set) {
         if (!structure->classInfo()->isSubClassOf(classInfo))
             return false;
     }
@@ -359,7 +367,7 @@ void StructureAbstractValue::dumpInContext(PrintStream& out, DumpContext* contex
     if (isTop())
         out.print("TOP");
     else
-        out.print(inContext(m_set, context));
+        out.print(inContext(m_set.toStructureSet(), context));
 }
 
 void StructureAbstractValue::dump(PrintStream& out) const
index 51f7937..5c6adc7 100644 (file)
 
 #if ENABLE(DFG_JIT)
 
+#include "DFGRegisteredStructureSet.h"
 #include "DFGTransition.h"
+#include "DumpContext.h"
 #include "JSCell.h"
 #include "SpeculatedType.h"
-#include "DumpContext.h"
 #include "StructureSet.h"
 
 namespace JSC {
@@ -42,12 +43,12 @@ namespace DFG {
 class StructureAbstractValue {
 public:
     StructureAbstractValue() { }
-    StructureAbstractValue(Structure* structure)
-        : m_set(StructureSet(structure))
+    StructureAbstractValue(RegisteredStructure structure)
+        : m_set(structure)
     {
         setClobbered(false);
     }
-    StructureAbstractValue(const StructureSet& other)
+    StructureAbstractValue(const RegisteredStructureSet& other)
         : m_set(other)
     {
         setClobbered(false);
@@ -58,13 +59,13 @@ public:
         setClobbered(other.isClobbered());
     }
     
-    ALWAYS_INLINE StructureAbstractValue& operator=(Structure* structure)
+    ALWAYS_INLINE StructureAbstractValue& operator=(RegisteredStructure structure)
     {
-        m_set = StructureSet(structure);
+        m_set = RegisteredStructureSet(structure);
         setClobbered(false);
         return *this;
     }
-    ALWAYS_INLINE StructureAbstractValue& operator=(const StructureSet& other)
+    ALWAYS_INLINE StructureAbstractValue& operator=(const RegisteredStructureSet& other)
     {
         m_set = other;
         setClobbered(false);
@@ -98,7 +99,7 @@ public:
     void clobber();
     void observeInvalidationPoint() { setClobbered(false); }
     
-    void observeTransition(Structure* from, Structure* to);
+    void observeTransition(RegisteredStructure from, RegisteredStructure to);
     void observeTransitions(const TransitionVector&);
     
     static StructureAbstractValue top()
@@ -131,9 +132,9 @@ public:
     // An infinite structure abstract value may currently have any structure.
     bool isInfinite() const { return !isFinite(); }
     
-    bool add(Structure* structure);
+    bool add(RegisteredStructure);
     
-    bool merge(const StructureSet& other);
+    bool merge(const RegisteredStructureSet& other);
     
     ALWAYS_INLINE bool merge(const StructureAbstractValue& other)
     {
@@ -151,7 +152,7 @@ public:
         return mergeSlow(other);
     }
     
-    void filter(const StructureSet& other);
+    void filter(const RegisteredStructureSet& other);
     void filter(const StructureAbstractValue& other);
     
     ALWAYS_INLINE void filter(SpeculatedType type)
@@ -178,11 +179,17 @@ public:
         return equalsSlow(other);
     }
     
-    const StructureSet& set() const
+    const RegisteredStructureSet& set() const
     {
         ASSERT(!isTop());
         return m_set;
     }
+
+    StructureSet toStructureSet() const
+    {
+        RELEASE_ASSERT(isFinite());
+        return m_set.toStructureSet();
+    }
     
     size_t size() const
     {
@@ -190,21 +197,21 @@ public:
         return m_set.size();
     }
     
-    Structure* at(size_t i) const
+    RegisteredStructure at(size_t i) const
     {
         ASSERT(!isTop());
         return m_set.at(i);
     }
     
-    Structure* operator[](size_t i) const { return at(i); }
+    RegisteredStructure operator[](size_t i) const { return at(i); }
 
     // In most cases, what you really want to do is verify whether the set is top or clobbered, and
     // if not, enumerate the set of structures. Use this only in cases where the singleton case is
     // meaningfully special, like for transitions.
-    Structure* onlyStructure() const
+    RegisteredStructure onlyStructure() const
     {
         if (isInfinite())
-            return nullptr;
+            return RegisteredStructure();
         return m_set.onlyStructure();
     }
 
@@ -224,18 +231,19 @@ public:
     // optimizations as a consequence of the "this is smaller" return value - so false for
     // contains(), true for isSubsetOf(), false for isSupersetOf(), and false for overlaps().
 
+    bool contains(RegisteredStructure) const;
     bool contains(Structure* structure) const;
     
-    bool isSubsetOf(const StructureSet& other) const;
+    bool isSubsetOf(const RegisteredStructureSet& other) const;
     bool isSubsetOf(const StructureAbstractValue& other) const;
     
-    bool isSupersetOf(const StructureSet& other) const;
+    bool isSupersetOf(const RegisteredStructureSet& other) const;
     bool isSupersetOf(const StructureAbstractValue& other) const
     {
         return other.isSubsetOf(*this);
     }
     
-    bool overlaps(const StructureSet& other) const;
+    bool overlaps(const RegisteredStructureSet& other) const;
     bool overlaps(const StructureAbstractValue& other) const;
 
     bool isSubClassOf(const ClassInfo*) const;
@@ -243,8 +251,8 @@ public:
     void validateReferences(const TrackedReferences&) const;
     
 private:
-    static const uintptr_t clobberedFlag = StructureSet::reservedFlag;
-    static const uintptr_t topValue = StructureSet::reservedValue;
+    static const uintptr_t clobberedFlag = RegisteredStructureSet::reservedFlag;
+    static const uintptr_t topValue = RegisteredStructureSet::reservedValue;
     static const unsigned polymorphismLimit = 10;
     static const unsigned clobberedSupremacyThreshold = 2;
     
@@ -260,7 +268,7 @@ private:
         m_set.m_pointer = topValue;
     }
     
-    bool mergeNotTop(const StructureSet& other);
+    bool mergeNotTop(const RegisteredStructureSet& other);
     
     void setClobbered(bool clobbered)
     {
@@ -268,7 +276,7 @@ private:
         m_set.setReservedFlag(clobbered);
     }
     
-    StructureSet m_set;
+    RegisteredStructureSet m_set;
 };
 
 } } // namespace JSC::DFG
diff --git a/Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp b/Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp
deleted file mode 100644 (file)
index af01641..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include "config.h"
-#include "DFGStructureRegistrationPhase.h"
-
-#if ENABLE(DFG_JIT)
-
-#include "DFGBasicBlockInlines.h"
-#include "DFGGraph.h"
-#include "DFGPhase.h"
-#include "JSCInlines.h"
-
-namespace JSC { namespace DFG {
-
-class StructureRegistrationPhase : public Phase {
-public:
-    StructureRegistrationPhase(Graph& graph)
-        : Phase(graph, "structure registration")
-    {
-    }
-    
-    bool run()
-    {
-        // FIXME: This phase shouldn't exist. We should have registered all structures by now, since
-        // we may already have done optimizations that rely on structures having been registered.
-        // Currently, we still have places where we don't register structures prior to this phase,
-        // but structures don't end up being used for optimization prior to this phase. That's a
-        // pretty fragile situation and we should fix it eventually.
-        // https://bugs.webkit.org/show_bug.cgi?id=147889
-        
-        // We need to set this before this phase finishes. This phase doesn't do anything
-        // conditioned on this field, except for assertIsRegistered() below. We intend for that
-        // method to behave as if the phase was already finished. So, we set this up here.
-        m_graph.m_structureRegistrationState = AllStructuresAreRegistered;
-        
-        // These are pretty dumb, but needed to placate subsequent assertions. We don't actually
-        // have to watch these because there is no way to transition away from it, but they are
-        // watchable and so we will assert if they aren't watched.
-        registerStructure(m_graph.m_vm.structureStructure.get());
-        registerStructure(m_graph.m_vm.stringStructure.get());
-        registerStructure(m_graph.m_vm.symbolStructure.get());
-        
-        for (FrozenValue* value : m_graph.m_frozenValues)
-            assertIsRegistered(value->structure());
-        
-        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
-            BasicBlock* block = m_graph.block(blockIndex);
-            if (!block)
-                continue;
-        
-            for (auto* node : *block) {
-                switch (node->op()) {
-                case CheckStructure:
-                    assertAreRegistered(node->structureSet());
-                    break;
-                
-                case NewObject:
-                case ArrayifyToStructure:
-                case NewStringObject:
-                    registerStructure(node->structure());
-                    break;
-                
-                case PutStructure:
-                case AllocatePropertyStorage:
-                case ReallocatePropertyStorage:
-                    registerStructure(node->transition()->previous);
-                    registerStructure(node->transition()->next);
-                    break;
-
-                case GetGetterSetterByOffset:
-                    registerStructure(m_graph.globalObjectFor(node->origin.semantic)->getterSetterStructure());
-                    break;
-
-                case MultiGetByOffset:
-                    for (const MultiGetByOffsetCase& getCase : node->multiGetByOffsetData().cases)
-                        registerStructures(getCase.set());
-                    break;
-                    
-                case MultiPutByOffset:
-                    for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
-                        PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
-                        registerStructures(variant.oldStructure());
-                        if (variant.kind() == PutByIdVariant::Transition)
-                            registerStructure(variant.newStructure());
-                    }
-                    break;
-                    
-                case NewArray:
-                case NewArrayBuffer:
-                case NewArrayWithSize: {
-                    JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
-                    registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
-                    registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithSlowPutArrayStorage));
-                    break;
-                }
-
-                case NewArrayWithSpread: {
-                    JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
-                    if (m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
-                        // We've compiled assuming we're not having a bad time, so to be consistent
-                        // with AI we must say we produce an original array allocation structure.
-                        registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous));
-                    } else
-                        registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous));
-                    break;
-                }
-
-                case Spread: {
-                    registerStructure(m_graph.m_vm.fixedArrayStructure.get());
-                    break;
-                }
-
-                case CreateRest: {
-                    if (m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
-                        JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
-                        registerStructure(globalObject->restParameterStructure());
-                    }
-                    break;
-                }
-                    
-                case NewTypedArray:
-                    registerStructure(m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructureConcurrently(node->typedArrayType()));
-                    break;
-                    
-                case ToString:
-                case CallStringConstructor:
-                    registerStructure(m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure());
-                    break;
-                    
-                case CreateActivation:
-                    registerStructure(m_graph.globalObjectFor(node->origin.semantic)->activationStructure());
-                    break;
-                    
-                case CreateDirectArguments:
-                    registerStructure(m_graph.globalObjectFor(node->origin.semantic)->directArgumentsStructure());
-                    break;
-                    
-                case CreateScopedArguments:
-                    registerStructure(m_graph.globalObjectFor(node->origin.semantic)->scopedArgumentsStructure());
-                    break;
-
-                case CreateClonedArguments:
-                    registerStructure(m_graph.globalObjectFor(node->origin.semantic)->clonedArgumentsStructure());
-                    break;
-
-                case NewRegexp:
-                    registerStructure(m_graph.globalObjectFor(node->origin.semantic)->regExpStructure());
-                    break;
-                case NewFunction:
-                    registerStructure(m_graph.globalObjectFor(node->origin.semantic)->functionStructure());
-                    break;
-                case NewGeneratorFunction:
-                    registerStructure(m_graph.globalObjectFor(node->origin.semantic)->generatorFunctionStructure());
-                    break;
-                case NewAsyncFunction:
-                    registerStructure(m_graph.globalObjectFor(node->origin.semantic)->asyncFunctionStructure());
-                    break;
-
-                default:
-                    break;
-                }
-            }
-        }
-        
-        return true;
-    }
-
-private:
-    void registerStructures(const StructureSet& set)
-    {
-        for (Structure* structure : set)
-            registerStructure(structure);
-    }
-    
-    void registerStructure(Structure* structure)
-    {
-        if (structure)
-            m_graph.registerStructure(structure);
-    }
-
-    void assertAreRegistered(const StructureSet& set)
-    {
-        for (Structure* structure : set)
-            assertIsRegistered(structure);
-    }
-
-    void assertIsRegistered(Structure* structure)
-    {
-        if (structure)
-            m_graph.assertIsRegistered(structure);
-    }
-};
-
-bool performStructureRegistration(Graph& graph)
-{
-    return runPhase<StructureRegistrationPhase>(graph);
-}
-
-} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
-
index 80d9b99..a54ec34 100644 (file)
@@ -34,7 +34,7 @@ namespace JSC { namespace DFG {
 
 void Transition::dumpInContext(PrintStream& out, DumpContext* context) const
 {
-    out.print(pointerDumpInContext(previous, context), " -> ", pointerDumpInContext(next, context));
+    out.print(pointerDumpInContext(previous.get(), context), " -> ", pointerDumpInContext(next.get(), context));
 }
 
 void Transition::dump(PrintStream& out) const
index 4605678..8d01e11 100644 (file)
@@ -27,6 +27,7 @@
 
 #if ENABLE(DFG_JIT)
 
+#include "DFGRegisteredStructure.h"
 #include <wtf/PrintStream.h>
 #include <wtf/Vector.h>
 
@@ -38,16 +39,12 @@ struct DumpContext;
 namespace DFG {
 
 struct Transition {
-    Structure* previous;
-    Structure* next;
+    RegisteredStructure previous;
+    RegisteredStructure next;
     
-    Transition()
-        : previous(nullptr)
-        , next(nullptr)
-    {
-    }
+    Transition() = default;
     
-    Transition(Structure* previous, Structure* next)
+    Transition(RegisteredStructure previous, RegisteredStructure next)
         : previous(previous)
         , next(next)
     {
index 6e00cc6..93bf265 100644 (file)
@@ -465,23 +465,23 @@ private:
         return true;
     }
     
-    void noticeStructureCheck(VariableAccessData* variable, Structure* structure)
+    void noticeStructureCheck(VariableAccessData* variable, RegisteredStructure structure)
     {
-        HashMap<VariableAccessData*, CheckData>::AddResult result = m_map.add(variable, CheckData(structure));
+        HashMap<VariableAccessData*, CheckData>::AddResult result = m_map.add(variable, CheckData(structure.get()));
         if (result.isNewEntry)
             return;
-        if (result.iterator->value.m_structure == structure)
+        if (result.iterator->value.m_structure == structure.get())
             return;
         result.iterator->value.m_structure = 0;
     }
     
-    void noticeStructureCheck(VariableAccessData* variable, const StructureSet& set)
+    void noticeStructureCheck(VariableAccessData* variable, RegisteredStructureSet set)
     {
         if (set.size() != 1) {
-            noticeStructureCheck(variable, 0);
+            noticeStructureCheck(variable, RegisteredStructure());
             return;
         }
-        noticeStructureCheck(variable, set.onlyStructure());
+        noticeStructureCheck(variable, set.at(0));
     }
 
     void noticeCheckArray(VariableAccessData* variable, ArrayMode arrayMode)
@@ -501,22 +501,22 @@ private:
         result.iterator->value.disableCheckArrayHoisting();
     }
 
-    void noticeStructureCheckAccountingForArrayMode(VariableAccessData* variable, Structure* structure)
+    void noticeStructureCheckAccountingForArrayMode(VariableAccessData* variable, RegisteredStructure structure)
     {
         HashMap<VariableAccessData*, CheckData>::iterator result = m_map.find(variable);
         if (result == m_map.end())
             return;
         if (!result->value.m_arrayModeHoistingOkay || !result->value.m_arrayModeIsValid)
             return;
-        if (result->value.m_arrayMode.structureWouldPassArrayModeFiltering(structure))
+        if (result->value.m_arrayMode.structureWouldPassArrayModeFiltering(structure.get()))
             return;
         result->value.disableCheckArrayHoisting();
     }
 
-    void noticeStructureCheckAccountingForArrayMode(VariableAccessData* variable, const StructureSet& set)
+    void noticeStructureCheckAccountingForArrayMode(VariableAccessData* variable, RegisteredStructureSet set)
     {
         for (unsigned i = 0; i < set.size(); i++)
-            noticeStructureCheckAccountingForArrayMode(variable, set[i]);
+            noticeStructureCheckAccountingForArrayMode(variable, set.at(i));
     }
 
     HashMap<VariableAccessData*, CheckData> m_map;
index f35e483..1bfd3a8 100644 (file)
@@ -209,7 +209,7 @@ public:
                         || node->origin.forExit != previousNode->origin.forExit);
                 }
                 
-                VALIDATE((node), !node->hasStructure() || !!node->structure());
+                VALIDATE((node), !node->hasStructure() || !!node->structure().get());
                 VALIDATE((node), !node->hasCellOperand() || node->cellOperand()->value().isCell());
                 VALIDATE((node), !node->hasCellOperand() || !!node->cellOperand()->value());
                 
@@ -285,7 +285,7 @@ public:
                     }
                     break;
                 case MaterializeNewObject:
-                    for (Structure* structure : node->structureSet()) {
+                    for (RegisteredStructure structure : node->structureSet()) {
                         // This only supports structures that are JSFinalObject or JSArray.
                         VALIDATE(
                             (node),
@@ -565,7 +565,7 @@ private:
                     // CPS disallows int32 and double arrays. Those require weird type checks and
                     // conversions. They are not needed in the DFG right now. We should add support
                     // for these if the DFG ever needs it.
-                    for (Structure* structure : node->structureSet()) {
+                    for (RegisteredStructure structure : node->structureSet()) {
                         VALIDATE((node), !hasInt32(structure->indexingType()));
                         VALIDATE((node), !hasDouble(structure->indexingType()));
                     }
index f3ecad1..e7f88c2 100644 (file)
@@ -196,7 +196,9 @@ public:
         m_proc.addFastConstant(m_tagTypeNumber->key());
         m_proc.addFastConstant(m_tagMask->key());
         
-        m_out.storePtr(m_out.constIntPtr(codeBlock()), addressFor(CallFrameSlot::codeBlock));
+        // We don't want the CodeBlock to have a weak pointer to itself because
+        // that would cause it to always get collected.
+        m_out.storePtr(m_out.constIntPtr(bitwise_cast<intptr_t>(codeBlock())), addressFor(CallFrameSlot::codeBlock));
 
         // Stack Overflow Check.
         unsigned exitFrameSize = m_graph.requiredRegisterCountForExit() * sizeof(Register);
@@ -1560,7 +1562,7 @@ private:
         m_out.branch(isObject(value), usually(continuation), rarely(slowCase));
 
         m_out.appendTo(slowCase, continuation);
-        ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, m_out.operation(operationObjectConstructor), m_callFrame, m_out.constIntPtr(globalObject), value));
+        ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, m_out.operation(operationObjectConstructor), m_callFrame, weakPointer(globalObject), value));
         m_out.jump(continuation);
 
         m_out.appendTo(continuation, lastNext);
@@ -2664,7 +2666,7 @@ private:
             checkStructure(
                 m_out.load32(cell, m_heaps.JSCell_structureID), jsValueValue(cell),
                 exitKind, m_node->structureSet(),
-                [&] (Structure* structure) {
+                [&] (RegisteredStructure structure) {
                     return weakStructureID(structure);
                 });
             return;
@@ -2684,7 +2686,7 @@ private:
             checkStructure(
                 m_out.load32(value, m_heaps.JSCell_structureID), jsValueValue(value),
                 exitKind, m_node->structureSet(),
-                [&] (Structure* structure) {
+                [&] (RegisteredStructure structure) {
                     return weakStructureID(structure);
                 });
             m_out.jump(continuation);
@@ -2798,8 +2800,8 @@ private:
     {
         m_ftlState.jitCode->common.notifyCompilingStructureTransition(m_graph.m_plan, codeBlock(), m_node);
         
-        Structure* oldStructure = m_node->transition()->previous;
-        Structure* newStructure = m_node->transition()->next;
+        RegisteredStructure oldStructure = m_node->transition()->previous;
+        RegisteredStructure newStructure = m_node->transition()->next;
         ASSERT_UNUSED(oldStructure, oldStructure->indexingType() == newStructure->indexingType());
         ASSERT(oldStructure->typeInfo().inlineTypeFlags() == newStructure->typeInfo().inlineTypeFlags());
         ASSERT(oldStructure->typeInfo().type() == newStructure->typeInfo().type());
@@ -3899,10 +3901,10 @@ private:
             // with one of the following indexing shapes: Int32, Contiguous, Double.
             LValue structure = m_out.select(
                 m_out.equal(indexingType, m_out.constInt32(ArrayWithInt32)),
-                m_out.constIntPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithInt32)),
+                weakStructure(m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithInt32))),
                 m_out.select(m_out.equal(indexingType, m_out.constInt32(ArrayWithContiguous)),
-                    m_out.constIntPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous)),
-                    m_out.constIntPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithDouble))));
+                    weakStructure(m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous))),
+                    weakStructure(m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithDouble)))));
             arrayResult = allocateJSArray(resultLength, structure, indexingType, false, false);
         }
 
@@ -3994,13 +3996,13 @@ private:
     {
         LValue scope = lowCell(m_node->child1());
         SymbolTable* table = m_node->castOperand<SymbolTable*>();
-        Structure* structure = m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure();
+        RegisteredStructure structure = m_graph.registerStructure(m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure());
         JSValue initializationValue = m_node->initializationValueForActivation();
         ASSERT(initializationValue.isUndefined() || initializationValue == jsTDZValue());
         if (table->singletonScope()->isStillValid()) {
             LValue callResult = vmCall(
                 Int64,
-                m_out.operation(operationCreateActivationDirect), m_callFrame, weakPointer(structure),
+                m_out.operation(operationCreateActivationDirect), m_callFrame, weakStructure(structure),
                 scope, weakPointer(table), m_out.constInt64(JSValue::encode(initializationValue)));
             setJSValue(callResult);
             return;
@@ -4035,7 +4037,7 @@ private:
             [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
                 return createLazyCallGenerator(
                     operationCreateActivationDirect, locations[0].directGPR(),
-                    CCallHelpers::TrustedImmPtr(structure), locations[1].directGPR(),
+                    CCallHelpers::TrustedImmPtr(structure.get()), locations[1].directGPR(),
                     CCallHelpers::TrustedImmPtr(table),
                     CCallHelpers::TrustedImm64(JSValue::encode(initializationValue)));
             },
@@ -4065,10 +4067,10 @@ private:
             return;
         }
         
-        Structure* structure =
+        RegisteredStructure structure = m_graph.registerStructure(
             isGeneratorFunction ? m_graph.globalObjectFor(m_node->origin.semantic)->generatorFunctionStructure() :
             isAsyncFunction ? m_graph.globalObjectFor(m_node->origin.semantic)->asyncFunctionStructure() :
-            m_graph.globalObjectFor(m_node->origin.semantic)->functionStructure();
+            m_graph.globalObjectFor(m_node->origin.semantic)->functionStructure());
         
         LBasicBlock slowPath = m_out.newBlock();
         LBasicBlock continuation = m_out.newBlock();
@@ -4128,8 +4130,8 @@ private:
         // them be explicit arguments to this node.
         // https://bugs.webkit.org/show_bug.cgi?id=142207
         
-        Structure* structure =
-            m_graph.globalObjectFor(m_node->origin.semantic)->directArgumentsStructure();
+        RegisteredStructure structure =
+            m_graph.registerStructure(m_graph.globalObjectFor(m_node->origin.semantic)->directArgumentsStructure());
         
         unsigned minCapacity = m_graph.baselineCodeBlockFor(m_node->origin.semantic)->numParameters() - 1;
         
@@ -4171,7 +4173,7 @@ private:
             [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
                 return createLazyCallGenerator(
                     operationCreateDirectArguments, locations[0].directGPR(),
-                    CCallHelpers::TrustedImmPtr(structure), locations[1].directGPR(),
+                    CCallHelpers::TrustedImmPtr(structure.get()), locations[1].directGPR(),
                     CCallHelpers::TrustedImm32(minCapacity));
             }, length.value);
         ValueFromBlock slowResult = m_out.anchor(callResult);
@@ -4259,7 +4261,7 @@ private:
             LValue arrayLength = lowInt32(m_node->child1());
             LBasicBlock loopStart = m_out.newBlock();
             JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
-            Structure* structure = globalObject->restParameterStructure();
+            RegisteredStructure structure = m_graph.registerStructure(globalObject->restParameterStructure());
             ArrayValues arrayValues = allocateUninitializedContiguousJSArray(arrayLength, structure);
             LValue array = arrayValues.array;
             LValue butterfly = arrayValues.butterfly;
@@ -4327,8 +4329,8 @@ private:
             speculate(m_graph.varArgChild(m_node, operandIndex));
         
         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
-        Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(
-            m_node->indexingType());
+        RegisteredStructure structure = m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(
+            m_node->indexingType()));
 
         if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
             unsigned numElements = m_node->numChildren();
@@ -4373,7 +4375,7 @@ private:
         if (!m_node->numChildren()) {
             setJSValue(vmCall(
                 Int64, m_out.operation(operationNewEmptyArray), m_callFrame,
-                m_out.constIntPtr(structure)));
+                weakStructure(structure)));
             return;
         }
         
@@ -4394,7 +4396,7 @@ private:
         
         LValue result = vmCall(
             Int64, m_out.operation(operationNewArray), m_callFrame,
-            m_out.constIntPtr(structure), m_out.constIntPtr(buffer),
+            weakStructure(structure), m_out.constIntPtr(buffer),
             m_out.constIntPtr(m_node->numChildren()));
         
         m_out.storePtr(m_out.intPtrZero, m_out.absolute(scratchBuffer->activeLengthPtr()));
@@ -4434,7 +4436,7 @@ private:
                 }
             }
 
-            Structure* structure = m_graph.globalObjectFor(m_node->origin.semantic)->originalArrayStructureForIndexingType(ArrayWithContiguous);
+            RegisteredStructure structure = m_graph.registerStructure(m_graph.globalObjectFor(m_node->origin.semantic)->originalArrayStructureForIndexingType(ArrayWithContiguous));
             ArrayValues arrayValues = allocateUninitializedContiguousJSArray(length, structure);
             LValue result = arrayValues.array;
             LValue storage = arrayValues.butterfly;
@@ -4656,8 +4658,8 @@ private:
     void compileNewArrayBuffer()
     {
         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
-        Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(
-            m_node->indexingType());
+        RegisteredStructure structure = m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(
+            m_node->indexingType()));
         
         if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
             unsigned numElements = m_node->numConstants();
@@ -4686,7 +4688,7 @@ private:
         
         setJSValue(vmCall(
             Int64, m_out.operation(operationNewArrayBuffer), m_callFrame,
-            m_out.constIntPtr(structure), m_out.constIntPtr(m_node->startConstant()),
+            weakStructure(structure), m_out.constIntPtr(m_node->startConstant()),
             m_out.constIntPtr(m_node->numConstants())));
     }
 
@@ -4695,23 +4697,22 @@ private:
         LValue publicLength = lowInt32(m_node->child1());
         
         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
-        Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(
-            m_node->indexingType());
+        RegisteredStructure structure = m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(
+            m_node->indexingType()));
         
         if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
             IndexingType indexingType = m_node->indexingType();
             setJSValue(
                 allocateJSArray(
-                    publicLength, m_out.constIntPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType)), m_out.constInt32(indexingType)).array);
+                    publicLength, weakPointer(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType)), m_out.constInt32(indexingType)).array);
             mutatorFence();
             return;
         }
         
         LValue structureValue = m_out.select(
             m_out.aboveOrEqual(publicLength, m_out.constInt32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)),
-            m_out.constIntPtr(
-                globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)),
-            m_out.constIntPtr(structure));
+            weakStructure(m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage))),
+            weakStructure(structure));
         setJSValue(vmCall(Int64, m_out.operation(operationNewArrayWithSize), m_callFrame, structureValue, publicLength, m_out.intPtrZero));
     }
 
@@ -4722,7 +4723,7 @@ private:
         
         switch (m_node->child1().useKind()) {
         case Int32Use: {
-            Structure* structure = globalObject->typedArrayStructureConcurrently(type);
+            RegisteredStructure structure = m_graph.registerStructure(globalObject->typedArrayStructureConcurrently(type));
 
             LValue size = lowInt32(m_node->child1());
 
@@ -4781,7 +4782,7 @@ private:
                 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
                     return createLazyCallGenerator(
                         operationNewTypedArrayWithSizeForType(type), locations[0].directGPR(),
-                        CCallHelpers::TrustedImmPtr(structure), locations[1].directGPR(),
+                        CCallHelpers::TrustedImmPtr(structure.get()), locations[1].directGPR(),
                         locations[2].directGPR());
                 },
                 size, storageValue);
@@ -4813,7 +4814,7 @@ private:
     void compileAllocatePropertyStorage()
     {
         LValue object = lowCell(m_node->child1());
-        setStorage(allocatePropertyStorage(object, m_node->transition()->previous));
+        setStorage(allocatePropertyStorage(object, m_node->transition()->previous.get()));
     }
 
     void compileReallocatePropertyStorage()
@@ -4824,7 +4825,7 @@ private:
         
         setStorage(
             reallocatePropertyStorage(
-                object, oldStorage, transition->previous, transition->next));
+                object, oldStorage, transition->previous.get(), transition->next.get()));
     }
     
     void compileNukeStructureAndSetButterfly()
@@ -5286,11 +5287,11 @@ private:
         LBasicBlock continuation = m_out.newBlock();
         
         Vector<SwitchCase, 2> cases;
-        StructureSet baseSet;
+        RegisteredStructureSet baseSet;
         for (unsigned i = data.cases.size(); i--;) {
             MultiGetByOffsetCase getCase = data.cases[i];
             for (unsigned j = getCase.set().size(); j--;) {
-                Structure* structure = getCase.set()[j];
+                RegisteredStructure structure = getCase.set()[j];
                 baseSet.add(structure);
                 cases.append(SwitchCase(weakStructureID(structure), blocks[i], Weight(1)));
             }
@@ -5368,11 +5369,11 @@ private:
         LBasicBlock continuation = m_out.newBlock();
         
         Vector<SwitchCase, 2> cases;
-        StructureSet baseSet;
+        RegisteredStructureSet baseSet;
         for (unsigned i = data.variants.size(); i--;) {
             PutByIdVariant variant = data.variants[i];
             for (unsigned j = variant.oldStructure().size(); j--;) {
-                Structure* structure = variant.oldStructure()[j];
+                RegisteredStructure structure = m_graph.registerStructure(variant.oldStructure()[j]);
                 baseSet.add(structure);
                 cases.append(SwitchCase(weakStructureID(structure), blocks[i], Weight(1)));
             }
@@ -5413,7 +5414,7 @@ private:
                 ASSERT(variant.oldStructureForTransition()->typeInfo().inlineTypeFlags() == variant.newStructure()->typeInfo().inlineTypeFlags());
                 ASSERT(variant.oldStructureForTransition()->typeInfo().type() == variant.newStructure()->typeInfo().type());
                 m_out.store32(
-                    weakStructureID(variant.newStructure()), base, m_heaps.JSCell_structureID);
+                    weakStructureID(m_graph.registerStructure(variant.newStructure())), base, m_heaps.JSCell_structureID);
             }
             
             m_out.jump(continuation);
@@ -7746,11 +7747,11 @@ private:
         LValue index = m_out.bitAnd(mask, unmaskedIndex);
         LValue hashMapBucket = m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), buffer, m_out.zeroExt(index, Int64), ScaleEight));
         ValueFromBlock bucketResult = m_out.anchor(hashMapBucket);
-        m_out.branch(m_out.equal(hashMapBucket, m_out.constIntPtr(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::emptyValue())),
+        m_out.branch(m_out.equal(hashMapBucket, m_out.constIntPtr(bitwise_cast<intptr_t>(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::emptyValue()))),
             unsure(notPresentInTable), unsure(notEmptyValue));
 
         m_out.appendTo(notEmptyValue, notDeletedValue);
-        m_out.branch(m_out.equal(hashMapBucket, m_out.constIntPtr(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::deletedValue())),
+        m_out.branch(m_out.equal(hashMapBucket, m_out.constIntPtr(bitwise_cast<intptr_t>(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::deletedValue()))),
             unsure(loopAround), unsure(notDeletedValue));
 
         m_out.appendTo(notDeletedValue, loopAround);
@@ -8222,7 +8223,8 @@ private:
 
     void compileOverridesHasInstance()
     {
-        JSFunction* defaultHasInstanceFunction = jsCast<JSFunction*>(m_node->cellOperand()->value());
+        FrozenValue* defaultHasInstanceFunction = m_node->cellOperand();
+        ASSERT(defaultHasInstanceFunction->cell()->inherits(JSFunction::info()));
 
         LValue constructor = lowCell(m_node->child1());
         LValue hasInstance = lowJSValue(m_node->child2());
@@ -8233,7 +8235,7 @@ private:
         // Unlike in the DFG, we don't worry about cleaning this code up for the case where we have proven the hasInstanceValue is a constant as B3 should fix it for us.
 
         ValueFromBlock notDefaultHasInstanceResult = m_out.anchor(m_out.booleanTrue);
-        m_out.branch(m_out.notEqual(hasInstance, m_out.constIntPtr(defaultHasInstanceFunction)), unsure(continuation), unsure(defaultHasInstance));
+        m_out.branch(m_out.notEqual(hasInstance, frozenPointer(defaultHasInstanceFunction)), unsure(continuation), unsure(defaultHasInstance));
 
         LBasicBlock lastNext = m_out.appendTo(defaultHasInstance, continuation);
         ValueFromBlock implementsDefaultHasInstanceResult = m_out.anchor(m_out.testIsZero32(
@@ -8581,7 +8583,7 @@ private:
         LValue structure = lowCell(m_node->child1());
         checkStructure(
             structure, noValue(), BadCache, m_node->structureSet(),
-            [this] (Structure* structure) {
+            [this] (RegisteredStructure structure) {
                 return weakStructure(structure);
             });
     }
@@ -8606,7 +8608,7 @@ private:
             }
         }
         
-        const StructureSet& set = m_node->structureSet();
+        RegisteredStructureSet set = m_node->structureSet();
 
         Vector<LBasicBlock, 1> blocks(set.size());
         for (unsigned i = set.size(); i--;)
@@ -8616,7 +8618,7 @@ private:
         
         Vector<SwitchCase, 1> cases(set.size());
         for (unsigned i = set.size(); i--;)
-            cases[i] = SwitchCase(weakStructure(set[i]), blocks[i], Weight(1));
+            cases[i] = SwitchCase(weakStructure(set.at(i)), blocks[i], Weight(1));
         m_out.switchInstruction(
             lowCell(m_graph.varArgChild(m_node, 0)), cases, dummyDefault, Weight(0));
         
@@ -8627,7 +8629,7 @@ private:
         for (unsigned i = set.size(); i--;) {
             m_out.appendTo(blocks[i], i + 1 < set.size() ? blocks[i + 1] : dummyDefault);
             
-            Structure* structure = set[i];
+            RegisteredStructure structure = set.at(i);
             
             LValue object;
             LValue butterfly;
@@ -8709,7 +8711,7 @@ private:
                         [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
                             return createLazyCallGenerator(
                                 operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength,
-                                locations[0].directGPR(), CCallHelpers::TrustedImmPtr(structure),
+                                locations[0].directGPR(), CCallHelpers::TrustedImmPtr(structure.get()),
                                 locations[1].directGPR(), locations[2].directGPR());
                         },
                         vectorLength, butterflyValue);
@@ -8718,7 +8720,7 @@ private:
                         [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
                             return createLazyCallGenerator(
                                 operationNewObjectWithButterfly, locations[0].directGPR(),
-                                CCallHelpers::TrustedImmPtr(structure), locations[1].directGPR());
+                                CCallHelpers::TrustedImmPtr(structure.get()), locations[1].directGPR());
                         },
                         butterflyValue);
                 }
@@ -8891,7 +8893,7 @@ private:
         LValue scope = lowCell(m_graph.varArgChild(m_node, 1));
         SymbolTable* table = m_node->castOperand<SymbolTable*>();
         ASSERT(table == m_graph.varArgChild(m_node, 0)->castConstant<SymbolTable*>());
-        Structure* structure = m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure();
+        RegisteredStructure structure = m_graph.registerStructure(m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure());
 
         LBasicBlock slowPath = m_out.newBlock();
         LBasicBlock continuation = m_out.newBlock();
@@ -8918,7 +8920,7 @@ private:
             [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
                 return createLazyCallGenerator(
                     operationCreateActivationDirect, locations[0].directGPR(),
-                    CCallHelpers::TrustedImmPtr(structure), locations[1].directGPR(),
+                    CCallHelpers::TrustedImmPtr(structure.get()), locations[1].directGPR(),
                     CCallHelpers::TrustedImmPtr(table),
                     CCallHelpers::TrustedImm64(JSValue::encode(jsUndefined())));
             }, scope);
@@ -9043,11 +9045,12 @@ private:
 
     void compileNewRegexp()
     {
-        RegExp* regexp = m_node->castOperand<RegExp*>();
+        FrozenValue* regexp = m_node->cellOperand();
+        ASSERT(regexp->cell()->inherits(RegExp::info()));
         LValue result = vmCall(
             pointerType(),
             m_out.operation(operationNewRegexp), m_callFrame,
-            m_out.constIntPtr(regexp));
+            frozenPointer(regexp));
         
         setJSValue(result);
     }
@@ -9140,10 +9143,12 @@ private:
         CallSiteIndex callSiteIndex = m_ftlState.jitCode->common.addCodeOrigin(m_node->origin.semantic);
         
         m_out.storePtr(m_callFrame, packet, m_heaps.ShadowChicken_Packet_frame);
-        m_out.storePtr(m_out.constIntPtr(ShadowChicken::Packet::tailMarker()), packet, m_heaps.ShadowChicken_Packet_callee);
+        m_out.storePtr(m_out.constIntPtr(bitwise_cast<intptr_t>(ShadowChicken::Packet::tailMarker())), packet, m_heaps.ShadowChicken_Packet_callee);
         m_out.store64(thisValue, packet, m_heaps.ShadowChicken_Packet_thisValue);
         m_out.storePtr(scope, packet, m_heaps.ShadowChicken_Packet_scope);
-        m_out.storePtr(m_out.constIntPtr(codeBlock()), packet, m_heaps.ShadowChicken_Packet_codeBlock);
+        // We don't want the CodeBlock to have a weak pointer to itself because
+        // that would cause it to always get collected.
+        m_out.storePtr(m_out.constIntPtr(bitwise_cast<intptr_t>(codeBlock())), packet, m_heaps.ShadowChicken_Packet_codeBlock);
         m_out.store32(m_out.constInt32(callSiteIndex.bits()), packet, m_heaps.ShadowChicken_Packet_callSiteIndex);
     }
 
@@ -9234,7 +9239,7 @@ private:
     template<typename Functor>
     void checkStructure(
         LValue structureDiscriminant, const FormattedValue& formattedValue, ExitKind exitKind,
-        const StructureSet& set, const Functor& weakStructureDiscriminant)
+        RegisteredStructureSet set, const Functor& weakStructureDiscriminant)
     {
         if (set.isEmpty()) {
             terminate(exitKind);
@@ -9369,16 +9374,18 @@ private:
             speculate(BadType, jsValueValue(value), edge.node(), isNotSymbol(value, provenType(edge)));
             return;
 
-        case InferredType::ObjectWithStructure:
+        case InferredType::ObjectWithStructure: {
+            RegisteredStructure structure = m_graph.registerStructure(type.structure());
             speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
-            if (!abstractValue(edge).m_structure.isSubsetOf(StructureSet(type.structure()))) {
+            if (!abstractValue(edge).m_structure.isSubsetOf(RegisteredStructureSet(structure))) {
                 speculate(
                     BadType, jsValueValue(value), edge.node(),
                     m_out.notEqual(
                         m_out.load32(value, m_heaps.JSCell_structureID),
-                        weakStructureID(type.structure())));
+                        weakStructureID(structure)));
             }
             return;
+        }
 
         case InferredType::ObjectWithStructureOrOther: {
             LBasicBlock cellCase = m_out.newBlock();
@@ -9389,12 +9396,13 @@ private:
 
             LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
 
-            if (!abstractValue(edge).m_structure.isSubsetOf(StructureSet(type.structure()))) {
+            RegisteredStructure structure = m_graph.registerStructure(type.structure());
+            if (!abstractValue(edge).m_structure.isSubsetOf(RegisteredStructureSet(structure))) {
                 speculate(
                     BadType, jsValueValue(value), edge.node(),
                     m_out.notEqual(
                         m_out.load32(value, m_heaps.JSCell_structureID),
-                        weakStructureID(type.structure())));
+                        weakStructureID(structure)));
             }
 
             m_out.jump(continuation);
@@ -10493,9 +10501,9 @@ private:
         return result;
     }
 
-    LValue allocateObject(LValue allocator, Structure* structure, LValue butterfly, LBasicBlock slowPath)
+    LValue allocateObject(LValue allocator, RegisteredStructure structure, LValue butterfly, LBasicBlock slowPath)
     {
-        return allocateObject(allocator, m_out.constIntPtr(structure), butterfly, slowPath);
+        return allocateObject(allocator, weakStructure(structure), butterfly, slowPath);
     }
 
     LValue allocateObject(LValue allocator, LValue structure, LValue butterfly, LBasicBlock slowPath)
@@ -10589,7 +10597,7 @@ private:
     
     template<typename ClassType>
     LValue allocateVariableSizedObject(
-        LValue size, Structure* structure, LValue butterfly, LBasicBlock slowPath)
+        LValue size, RegisteredStructure structure, LValue butterfly, LBasicBlock slowPath)
     {
         LValue allocator = allocatorForSize(
             *subspaceFor<ClassType>(vm()), size, slowPath);
@@ -10605,9 +10613,9 @@ private:
         return allocateCell(allocator, structure, slowPath);
     }
     
-    LValue allocateObject(Structure* structure)
+    LValue allocateObject(RegisteredStructure structure)
     {
-        size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
+        size_t allocationSize = JSFinalObject::allocationSize(structure.get()->inlineCapacity());
         MarkedAllocator* allocator = subspaceFor<JSFinalObject>(vm())->allocatorFor(allocationSize);
         
         // FIXME: If the allocator is null, we could simply emit a normal C call to the allocator
@@ -10630,7 +10638,7 @@ private:
             [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
                 return createLazyCallGenerator(
                     operationNewObject, locations[0].directGPR(),
-                    CCallHelpers::TrustedImmPtr(structure));
+                    CCallHelpers::TrustedImmPtr(structure.get()));
             });
         ValueFromBlock slowResult = m_out.anchor(slowResultValue);
         m_out.jump(continuation);
@@ -10733,8 +10741,7 @@ private:
         
         m_out.appendTo(largeCase, failCase);
         ValueFromBlock largeStructure = m_out.anchor(
-            m_out.constIntPtr(
-                globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)));
+            weakStructure(m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage))));
         m_out.jump(slowCase);
         
         m_out.appendTo(failCase, slowCase);
@@ -10763,12 +10770,12 @@ private:
             m_out.phi(pointerType(), fastButterfly, slowButterfly));
     }
     
-    ArrayValues allocateUninitializedContiguousJSArray(LValue publicLength, Structure* structure)
+    ArrayValues allocateUninitializedContiguousJSArray(LValue publicLength, RegisteredStructure structure)
     {
         bool shouldInitializeElements = false;
         bool shouldLargeArraySizeCreateArrayStorage = false;
         return allocateJSArray(
-            publicLength, m_out.constIntPtr(structure), m_out.constInt32(structure->indexingType()), shouldInitializeElements,
+            publicLength, weakStructure(structure), m_out.constInt32(structure->indexingType()), shouldInitializeElements,
             shouldLargeArraySizeCreateArrayStorage);
     }
     
@@ -10910,7 +10917,7 @@ private:
                 m_out.appendTo(masqueradesCase);
                 
                 isTruthyObject = m_out.notEqual(
-                    m_out.constIntPtr(m_graph.globalObjectFor(m_node->origin.semantic)),
+                    weakPointer(m_graph.globalObjectFor(m_node->origin.semantic)),
                     m_out.loadPtr(loadStructure(value), m_heaps.Structure_globalObject));
             }
             results.append(m_out.anchor(isTruthyObject));
@@ -11009,7 +11016,7 @@ private:
             
             results.append(m_out.anchor(
                 m_out.equal(
-                    m_out.constIntPtr(m_graph.globalObjectFor(m_node->origin.semantic)),
+                    weakPointer(m_graph.globalObjectFor(m_node->origin.semantic)),
                     m_out.loadPtr(structure, m_heaps.Structure_globalObject))));
             m_out.jump(continuation);
         }
@@ -11931,12 +11938,12 @@ private:
         DFG_ASSERT(m_graph, m_node, mode == ManualOperandSpeculation || DFG::isCell(edge.useKind()));
         
         if (edge->op() == JSConstant) {
-            JSValue value = edge->asJSValue();
-            if (!value.isCell()) {
+            FrozenValue* value = edge->constant();
+            if (!value->value().isCell()) {
                 terminate(Uncountable);
                 return m_out.intPtrZero;
             }
-            return m_out.constIntPtr(value.asCell());
+            return frozenPointer(value);
         }
         
         LoweredNodeValue value = m_jsValueValues.get(edge.node());
@@ -12901,10 +12908,10 @@ private:
     
     void speculateStringObjectForStructureID(Edge edge, LValue structureID)
     {
-        Structure* stringObjectStructure =
-            m_graph.globalObjectFor(m_node->origin.semantic)->stringObjectStructure();
-        
-        if (abstractStructure(edge).isSubsetOf(StructureSet(stringObjectStructure)))
+        RegisteredStructure stringObjectStructure =
+            m_graph.registerStructure(m_graph.globalObjectFor(m_node->origin.semantic)->stringObjectStructure());
+
+        if (abstractStructure(edge).isSubsetOf(RegisteredStructureSet(stringObjectStructure)))
             return;
         
         speculate(
@@ -13689,19 +13696,30 @@ private:
 
     LValue weakPointer(JSCell* pointer)
     {
+        // There are weird relationships in how optimized CodeBlocks
+        // point to other CodeBlocks. We don't want to have them be
+        // part of the weak pointer set. For example, an optimized CodeBlock
+        // having a weak pointer to itself will cause it to get collected.
+        RELEASE_ASSERT(!jsDynamicCast<CodeBlock*>(pointer));
+
         addWeakReference(pointer);
-        return m_out.constIntPtr(pointer);
+        return m_out.weakPointer(m_graph, pointer);
+    }
+
+    LValue frozenPointer(FrozenValue* value)
+    {
+        return m_out.weakPointer(value);
     }
 
-    LValue weakStructureID(Structure* structure)
+    LValue weakStructureID(RegisteredStructure structure)
     {
-        addWeakReference(structure);
         return m_out.constInt32(structure->id());
     }
     
-    LValue weakStructure(Structure* structure)
+    LValue weakStructure(RegisteredStructure structure)
     {
-        return weakPointer(structure);
+        ASSERT(!!structure.get());
+        return m_out.weakPointer(m_graph, structure.get());
     }
     
     TypedPointer addressFor(LValue base, int operand, ptrdiff_t offset = 0)
@@ -13809,7 +13827,9 @@ private:
         m_out.call(
             Void,
             m_out.constIntPtr(ftlUnreachable),
-            m_out.constIntPtr(codeBlock()), m_out.constInt32(blockIndex),
+            // We don't want the CodeBlock to have a weak pointer to itself because
+            // that would cause it to always get collected.
+            m_out.constIntPtr(bitwise_cast<intptr_t>(codeBlock())), m_out.constInt32(blockIndex),
             m_out.constInt32(nodeIndex));
 #endif
         m_out.unreachable();
index daea7d0..433e1e0 100644 (file)
@@ -44,6 +44,7 @@
 #include "FTLValueFromBlock.h"
 #include "FTLWeight.h"
 #include "FTLWeightedTarget.h"
+#include "HeapCell.h"
 #include <wtf/OrderMaker.h>
 #include <wtf/StringPrintStream.h>
 
@@ -104,9 +105,29 @@ public:
 
     LValue constBool(bool value);
     LValue constInt32(int32_t value);
+
+    LValue weakPointer(DFG::Graph& graph, JSCell* cell)
+    {
+        ASSERT(graph.m_plan.weakReferences.contains(cell));
+
+        if (sizeof(void*) == 8)
+            return constInt64(bitwise_cast<intptr_t>(cell));
+        return constInt32(bitwise_cast<intptr_t>(cell));
+    }
+
+    LValue weakPointer(DFG::FrozenValue* value)
+    {
+        RELEASE_ASSERT(value->value().isCell());
+
+        if (sizeof(void*) == 8)
+            return constInt64(bitwise_cast<intptr_t>(value->cell()));
+        return constInt32(bitwise_cast<intptr_t>(value->cell()));
+    }
+
     template<typename T>
     LValue constIntPtr(T* value)
     {
+        static_assert(!std::is_base_of<HeapCell, T>::value, "To use a GC pointer, the graph must be aware of it. Use gcPointer instead and make sure the graph is aware of this reference.");
         if (sizeof(void*) == 8)
             return constInt64(bitwise_cast<intptr_t>(value));
         return constInt32(bitwise_cast<intptr_t>(value));
index b0311ca..faf5437 100644 (file)
@@ -1,3 +1,25 @@
+2017-01-26  Saam Barati  <sbarati@apple.com>
+
+        Harden how the compiler references GC objects
+        https://bugs.webkit.org/show_bug.cgi?id=167277
+        <rdar://problem/30179506>
+
+        Reviewed by Filip Pizlo.
+
+        I made TinyPtrSet use bitwise_cast instead of static_cast
+        for its singleEntry() function so that it can work on pointer-like
+        types just as it can on actual pointer types.
+        
+        An example of where this matters is when you have TinyPtrSet<T>
+        where T is defined to be a struct which wraps a pointer, e.g:
+        
+        struct T {
+            void* m_pointer;
+        }
+
+        * wtf/TinyPtrSet.h:
+        (WTF::TinyPtrSet::singleEntry):
+
 2017-01-25  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         Introduce an item-provider-based pasteboard wrapper
index 0086cc5..f67e944 100644 (file)
@@ -43,6 +43,7 @@ namespace WTF {
 
 template<typename T>
 class TinyPtrSet {
+    static_assert(sizeof(T) == sizeof(void*), "It's in the title of the class.");
 public:
     TinyPtrSet()
         : m_pointer(0)
@@ -475,7 +476,7 @@ private:
     T singleEntry() const
     {
         ASSERT(isThin());
-        return static_cast<T>(pointer());
+        return bitwise_cast<T>(pointer());
     }
     
     OutOfLineList* list() const