Unreviewed, partially reverting Structure change due to Speedometer2 regression
authorysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 3 Apr 2020 15:58:59 +0000 (15:58 +0000)
committerysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 3 Apr 2020 15:58:59 +0000 (15:58 +0000)
https://bugs.webkit.org/show_bug.cgi?id=207827

Not reverting WTF changes.

* bytecode/AccessCase.cpp:
(JSC::AccessCase::createTransition):
(JSC::AccessCase::createDelete):
(JSC::AccessCase::propagateTransitions const):
* bytecode/AccessCase.h:
(JSC::AccessCase::structure const):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileCheckSubClass):
(JSC::DFG::SpeculativeJIT::compileObjectKeys):
(JSC::DFG::SpeculativeJIT::compileCreateThis):
(JSC::DFG::SpeculativeJIT::compileCreatePromise):
(JSC::DFG::SpeculativeJIT::compileCreateInternalFieldObject):
* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileObjectKeys):
(JSC::FTL::DFG::LowerDFGToB3::compileCreatePromise):
(JSC::FTL::DFG::LowerDFGToB3::compileCreateInternalFieldObject):
(JSC::FTL::DFG::LowerDFGToB3::compileCheckSubClass):
(JSC::FTL::DFG::LowerDFGToB3::loadStructureClassInfo): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::loadStructureCachedPrototypeChainOrRareData): Deleted.
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::emitLoadClassInfoFromStructure): Deleted.
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_create_this):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_create_this):
* jit/Repatch.cpp:
(JSC::tryCachePutByID):
(JSC::tryCacheDeleteBy):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/ClonedArguments.cpp:
(JSC::ClonedArguments::createStructure):
* runtime/ConcurrentJSLock.h:
(JSC::ConcurrentJSLockerBase::ConcurrentJSLockerBase):
(JSC::GCSafeConcurrentJSLocker::GCSafeConcurrentJSLocker):
(JSC::GCSafeConcurrentJSLocker::~GCSafeConcurrentJSLocker):
(JSC::ConcurrentJSLocker::ConcurrentJSLocker):
(JSC::GCSafeConcurrentJSLockerImpl::GCSafeConcurrentJSLockerImpl): Deleted.
(JSC::GCSafeConcurrentJSLockerImpl::~GCSafeConcurrentJSLockerImpl): Deleted.
(JSC::ConcurrentJSLockerImpl::ConcurrentJSLockerImpl): Deleted.
* runtime/JSCell.h:
* runtime/JSObject.cpp:
(JSC::JSObject::deleteProperty):
(JSC::JSObject::shiftButterflyAfterFlattening):
* runtime/JSObject.h:
(JSC::JSObject::getDirectConcurrently const):
* runtime/JSObjectInlines.h:
(JSC::JSObject::prepareToPutDirectWithoutTransition):
* runtime/JSType.cpp:
(WTF::printInternal):
* runtime/JSType.h:
* runtime/Structure.cpp:
(JSC::StructureTransitionTable::contains const):
(JSC::StructureTransitionTable::get const):
(JSC::StructureTransitionTable::add):
(JSC::Structure::dumpStatistics):
(JSC::Structure::Structure):
(JSC::Structure::create):
(JSC::Structure::findStructuresAndMapForMaterialization):
(JSC::Structure::materializePropertyTable):
(JSC::Structure::addPropertyTransitionToExistingStructureImpl):
(JSC::Structure::addPropertyTransitionToExistingStructureConcurrently):
(JSC::Structure::addNewPropertyTransition):
(JSC::Structure::removePropertyTransitionFromExistingStructureConcurrently):
(JSC::Structure::removeNewPropertyTransition):
(JSC::Structure::changePrototypeTransition):
(JSC::Structure::attributeChangeTransition):
(JSC::Structure::toDictionaryTransition):
(JSC::Structure::takePropertyTableOrCloneIfPinned):
(JSC::Structure::nonPropertyTransitionSlow):
(JSC::Structure::flattenDictionaryStructure):
(JSC::Structure::pin):
(JSC::Structure::pinForCaching):
(JSC::Structure::allocateRareData):
(JSC::Structure::ensurePropertyReplacementWatchpointSet):
(JSC::Structure::copyPropertyTableForPinning):
(JSC::Structure::add):
(JSC::Structure::remove):
(JSC::Structure::visitChildren):
(JSC::Structure::canCachePropertyNameEnumerator const):
* runtime/Structure.h:
* runtime/StructureInlines.h:
(JSC::Structure::get):
(JSC::Structure::forEachPropertyConcurrently):
(JSC::Structure::transitivelyTransitionedFrom):
(JSC::Structure::prototypeChain const):
(JSC::Structure::propertyReplacementWatchpointSet):
(JSC::Structure::checkOffsetConsistency const):
(JSC::Structure::add):
(JSC::Structure::remove):
(JSC::Structure::removePropertyWithoutTransition):
(JSC::Structure::setPropertyTable):
(JSC::Structure::setPreviousID):
(JSC::Structure::ruleOutUnseenProperty const): Deleted.
(JSC::Structure::seenProperties const): Deleted.
(JSC::Structure::addPropertyHashAndSeenProperty): Deleted.
(JSC::Structure::cachedPrototypeChain const): Deleted.
(JSC::Structure::setCachedPrototypeChain): Deleted.
(JSC::Structure::clearPropertyTable): Deleted.
(JSC::Structure::setOutOfLineTypeFlags): Deleted.
(JSC::Structure::setInlineCapacity): Deleted.
(JSC::Structure::setClassInfo): Deleted.
(JSC::Structure::clearPreviousID): Deleted.
* runtime/StructureRareData.cpp:
(JSC::StructureRareData::createStructure):
(JSC::StructureRareData::create):
(JSC::StructureRareData::StructureRareData):
(JSC::StructureRareData::visitChildren):
* runtime/StructureRareData.h:
* runtime/StructureRareDataInlines.h:
(JSC::StructureRareData::setPreviousID):
(JSC::StructureRareData::clearPreviousID):
(JSC::StructureRareData::setCachedPrototypeChain): Deleted.
* runtime/StructureTransitionTable.h:
* tools/JSDollarVM.cpp:
(JSC::JSDollarVMHelper::functionGetStructureTransitionList):
* wasm/js/WebAssemblyFunction.cpp:
(JSC::WebAssemblyFunction::jsCallEntrypointSlow):

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

28 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/AccessCase.cpp
Source/JavaScriptCore/bytecode/AccessCase.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/jit/AssemblyHelpers.h
Source/JavaScriptCore/jit/JITOpcodes.cpp
Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
Source/JavaScriptCore/jit/Repatch.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/runtime/ClonedArguments.cpp
Source/JavaScriptCore/runtime/ConcurrentJSLock.h
Source/JavaScriptCore/runtime/JSCell.h
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSObject.h
Source/JavaScriptCore/runtime/JSObjectInlines.h
Source/JavaScriptCore/runtime/JSType.cpp
Source/JavaScriptCore/runtime/JSType.h
Source/JavaScriptCore/runtime/Structure.cpp
Source/JavaScriptCore/runtime/Structure.h
Source/JavaScriptCore/runtime/StructureInlines.h
Source/JavaScriptCore/runtime/StructureRareData.cpp
Source/JavaScriptCore/runtime/StructureRareData.h
Source/JavaScriptCore/runtime/StructureRareDataInlines.h
Source/JavaScriptCore/runtime/StructureTransitionTable.h
Source/JavaScriptCore/tools/JSDollarVM.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp

index aa9d8a8..3158b1e 100644 (file)
@@ -1,3 +1,130 @@
+2020-04-03  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        Unreviewed, partially reverting Structure change due to Speedometer2 regression
+        https://bugs.webkit.org/show_bug.cgi?id=207827
+
+        Not reverting WTF changes.
+
+        * bytecode/AccessCase.cpp:
+        (JSC::AccessCase::createTransition):
+        (JSC::AccessCase::createDelete):
+        (JSC::AccessCase::propagateTransitions const):
+        * bytecode/AccessCase.h:
+        (JSC::AccessCase::structure const):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileCheckSubClass):
+        (JSC::DFG::SpeculativeJIT::compileObjectKeys):
+        (JSC::DFG::SpeculativeJIT::compileCreateThis):
+        (JSC::DFG::SpeculativeJIT::compileCreatePromise):
+        (JSC::DFG::SpeculativeJIT::compileCreateInternalFieldObject):
+        * ftl/FTLAbstractHeapRepository.h:
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileObjectKeys):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCreatePromise):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCreateInternalFieldObject):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCheckSubClass):
+        (JSC::FTL::DFG::LowerDFGToB3::loadStructureClassInfo): Deleted.
+        (JSC::FTL::DFG::LowerDFGToB3::loadStructureCachedPrototypeChainOrRareData): Deleted.
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::emitLoadClassInfoFromStructure): Deleted.
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_create_this):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_create_this):
+        * jit/Repatch.cpp:
+        (JSC::tryCachePutByID):
+        (JSC::tryCacheDeleteBy):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * runtime/ClonedArguments.cpp:
+        (JSC::ClonedArguments::createStructure):
+        * runtime/ConcurrentJSLock.h:
+        (JSC::ConcurrentJSLockerBase::ConcurrentJSLockerBase):
+        (JSC::GCSafeConcurrentJSLocker::GCSafeConcurrentJSLocker):
+        (JSC::GCSafeConcurrentJSLocker::~GCSafeConcurrentJSLocker):
+        (JSC::ConcurrentJSLocker::ConcurrentJSLocker):
+        (JSC::GCSafeConcurrentJSLockerImpl::GCSafeConcurrentJSLockerImpl): Deleted.
+        (JSC::GCSafeConcurrentJSLockerImpl::~GCSafeConcurrentJSLockerImpl): Deleted.
+        (JSC::ConcurrentJSLockerImpl::ConcurrentJSLockerImpl): Deleted.
+        * runtime/JSCell.h:
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::deleteProperty):
+        (JSC::JSObject::shiftButterflyAfterFlattening):
+        * runtime/JSObject.h:
+        (JSC::JSObject::getDirectConcurrently const):
+        * runtime/JSObjectInlines.h:
+        (JSC::JSObject::prepareToPutDirectWithoutTransition):
+        * runtime/JSType.cpp:
+        (WTF::printInternal):
+        * runtime/JSType.h:
+        * runtime/Structure.cpp:
+        (JSC::StructureTransitionTable::contains const):
+        (JSC::StructureTransitionTable::get const):
+        (JSC::StructureTransitionTable::add):
+        (JSC::Structure::dumpStatistics):
+        (JSC::Structure::Structure):
+        (JSC::Structure::create):
+        (JSC::Structure::findStructuresAndMapForMaterialization):
+        (JSC::Structure::materializePropertyTable):
+        (JSC::Structure::addPropertyTransitionToExistingStructureImpl):
+        (JSC::Structure::addPropertyTransitionToExistingStructureConcurrently):
+        (JSC::Structure::addNewPropertyTransition):
+        (JSC::Structure::removePropertyTransitionFromExistingStructureConcurrently):
+        (JSC::Structure::removeNewPropertyTransition):
+        (JSC::Structure::changePrototypeTransition):
+        (JSC::Structure::attributeChangeTransition):
+        (JSC::Structure::toDictionaryTransition):
+        (JSC::Structure::takePropertyTableOrCloneIfPinned):
+        (JSC::Structure::nonPropertyTransitionSlow):
+        (JSC::Structure::flattenDictionaryStructure):
+        (JSC::Structure::pin):
+        (JSC::Structure::pinForCaching):
+        (JSC::Structure::allocateRareData):
+        (JSC::Structure::ensurePropertyReplacementWatchpointSet):
+        (JSC::Structure::copyPropertyTableForPinning):
+        (JSC::Structure::add):
+        (JSC::Structure::remove):
+        (JSC::Structure::visitChildren):
+        (JSC::Structure::canCachePropertyNameEnumerator const):
+        * runtime/Structure.h:
+        * runtime/StructureInlines.h:
+        (JSC::Structure::get):
+        (JSC::Structure::forEachPropertyConcurrently):
+        (JSC::Structure::transitivelyTransitionedFrom):
+        (JSC::Structure::prototypeChain const):
+        (JSC::Structure::propertyReplacementWatchpointSet):
+        (JSC::Structure::checkOffsetConsistency const):
+        (JSC::Structure::add):
+        (JSC::Structure::remove):
+        (JSC::Structure::removePropertyWithoutTransition):
+        (JSC::Structure::setPropertyTable):
+        (JSC::Structure::setPreviousID):
+        (JSC::Structure::ruleOutUnseenProperty const): Deleted.
+        (JSC::Structure::seenProperties const): Deleted.
+        (JSC::Structure::addPropertyHashAndSeenProperty): Deleted.
+        (JSC::Structure::cachedPrototypeChain const): Deleted.
+        (JSC::Structure::setCachedPrototypeChain): Deleted.
+        (JSC::Structure::clearPropertyTable): Deleted.
+        (JSC::Structure::setOutOfLineTypeFlags): Deleted.
+        (JSC::Structure::setInlineCapacity): Deleted.
+        (JSC::Structure::setClassInfo): Deleted.
+        (JSC::Structure::clearPreviousID): Deleted.
+        * runtime/StructureRareData.cpp:
+        (JSC::StructureRareData::createStructure):
+        (JSC::StructureRareData::create):
+        (JSC::StructureRareData::StructureRareData):
+        (JSC::StructureRareData::visitChildren):
+        * runtime/StructureRareData.h:
+        * runtime/StructureRareDataInlines.h:
+        (JSC::StructureRareData::setPreviousID):
+        (JSC::StructureRareData::clearPreviousID):
+        (JSC::StructureRareData::setCachedPrototypeChain): Deleted.
+        * runtime/StructureTransitionTable.h:
+        * tools/JSDollarVM.cpp:
+        (JSC::JSDollarVMHelper::functionGetStructureTransitionList):
+        * wasm/js/WebAssemblyFunction.cpp:
+        (JSC::WebAssemblyFunction::jsCallEntrypointSlow):
+
 2020-04-02  Alexey Shvayka  <shvaikalesh@gmail.com>
 
         TypedArray's [[DefineOwnProperty]] is incorrect with partial descriptors
index e45da69..f6f7bd1 100644 (file)
@@ -112,7 +112,7 @@ std::unique_ptr<AccessCase> AccessCase::createTransition(
     VM& vm, JSCell* owner, CacheableIdentifier identifier, PropertyOffset offset, Structure* oldStructure, Structure* newStructure,
     const ObjectPropertyConditionSet& conditionSet, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain)
 {
-    RELEASE_ASSERT(oldStructure == newStructure->previousID(vm));
+    RELEASE_ASSERT(oldStructure == newStructure->previousID());
 
     // Skip optimizing the case where we need a realloc, if we don't have
     // enough registers to make it happen.
@@ -128,7 +128,7 @@ std::unique_ptr<AccessCase> AccessCase::createTransition(
 std::unique_ptr<AccessCase> AccessCase::createDelete(
     VM& vm, JSCell* owner, CacheableIdentifier identifier, PropertyOffset offset, Structure* oldStructure, Structure* newStructure)
 {
-    RELEASE_ASSERT(oldStructure == newStructure->previousID(vm));
+    RELEASE_ASSERT(oldStructure == newStructure->previousID());
     // We do not cache this case so that we do not need to check the jscell, e.g. TypedArray cells require a check for neutering status.
     // See the Delete code below.
     if (!newStructure->canCacheDeleteIC())
@@ -742,7 +742,7 @@ bool AccessCase::propagateTransitions(SlotVisitor& visitor) const
     switch (m_type) {
     case Transition:
     case Delete:
-        if (visitor.vm().heap.isMarked(m_structure->previousID(visitor.vm())))
+        if (visitor.vm().heap.isMarked(m_structure->previousID()))
             visitor.appendUnbarriered(m_structure.get());
         else
             result = false;
index a3479d1..108fef3 100644 (file)
@@ -163,7 +163,7 @@ public:
     Structure* structure() const
     {
         if (m_type == Transition || m_type == Delete)
-            return m_structure->previousID(m_structure->vm());
+            return m_structure->previousID();
         return m_structure.get();
     }
     bool guardedByStructureCheck(const StructureStubInfo&) const;
index 82e695d..caa4bab 100644 (file)
@@ -9568,7 +9568,7 @@ void SpeculativeJIT::compileCheckSubClass(Node* node)
         GPRReg specifiedGPR = specified.gpr();
 
         m_jit.emitLoadStructure(vm(), baseGPR, otherGPR, specifiedGPR);
-        m_jit.emitLoadClassInfoFromStructure(otherGPR, otherGPR);
+        m_jit.loadPtr(CCallHelpers::Address(otherGPR, Structure::classInfoOffset()), otherGPR);
         m_jit.move(CCallHelpers::TrustedImmPtr(node->classInfo()), specifiedGPR);
 
         CCallHelpers::Label loop = m_jit.label();
@@ -12661,13 +12661,10 @@ void SpeculativeJIT::compileObjectKeys(Node* node)
 
             CCallHelpers::JumpList slowCases;
             m_jit.emitLoadStructure(vm(), objectGPR, structureGPR, scratchGPR);
-            m_jit.loadPtr(CCallHelpers::Address(structureGPR, Structure::offsetOfCachedPrototypeChainOrRareData()), scratchGPR);
-#if CPU(ADDRESS64)
-            m_jit.andPtr(CCallHelpers::TrustedImmPtr(Structure::cachedPrototypeChainOrRareDataMask), scratchGPR);
-#endif
+            m_jit.loadPtr(CCallHelpers::Address(structureGPR, Structure::previousOrRareDataOffset()), scratchGPR);
 
             slowCases.append(m_jit.branchTestPtr(CCallHelpers::Zero, scratchGPR));
-            slowCases.append(m_jit.branch32(CCallHelpers::NotEqual, CCallHelpers::Address(scratchGPR, JSCell::structureIDOffset()), TrustedImm32(bitwise_cast<int32_t>(vm().structureRareDataStructure->structureID()))));
+            slowCases.append(m_jit.branch32(CCallHelpers::Equal, CCallHelpers::Address(scratchGPR, JSCell::structureIDOffset()), TrustedImm32(bitwise_cast<int32_t>(vm().structureStructure->structureID()))));
 
             m_jit.loadPtr(CCallHelpers::Address(scratchGPR, StructureRareData::offsetOfCachedOwnKeys()), scratchGPR);
 
@@ -12805,7 +12802,7 @@ void SpeculativeJIT::compileCreateThis(Node* node)
     auto butterfly = TrustedImmPtr(nullptr);
     emitAllocateJSObject(resultGPR, JITAllocator::variable(), allocatorGPR, structureGPR, butterfly, scratchGPR, slowPath);
 
-    m_jit.load8(JITCompiler::Address(structureGPR, Structure::offsetOfInlineCapacity()), inlineCapacityGPR);
+    m_jit.load8(JITCompiler::Address(structureGPR, Structure::inlineCapacityOffset()), inlineCapacityGPR);
     m_jit.emitInitializeInlineStorage(resultGPR, inlineCapacityGPR);
     m_jit.mutatorFence(vm());
 
@@ -12843,8 +12840,8 @@ void SpeculativeJIT::compileCreatePromise(Node* node)
     slowCases.append(m_jit.branchTestPtr(MacroAssembler::Zero, rareDataGPR, CCallHelpers::TrustedImm32(JSFunction::rareDataTag)));
     m_jit.loadPtr(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfInternalFunctionAllocationProfile() + InternalFunctionAllocationProfile::offsetOfStructure() - JSFunction::rareDataTag), structureGPR);
     slowCases.append(m_jit.branchTestPtr(CCallHelpers::Zero, structureGPR));
-    m_jit.emitLoadClassInfoFromStructure(structureGPR, scratch1GPR);
-    slowCases.append(m_jit.branchPtr(CCallHelpers::NotEqual, scratch1GPR, TrustedImmPtr(node->isInternalPromise() ? JSInternalPromise::info() : JSPromise::info())));
+    m_jit.move(TrustedImmPtr(node->isInternalPromise() ? JSInternalPromise::info() : JSPromise::info()), scratch1GPR);
+    slowCases.append(m_jit.branchPtr(CCallHelpers::NotEqual, scratch1GPR, CCallHelpers::Address(structureGPR, Structure::classInfoOffset())));
     m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), globalObject), scratch1GPR);
     slowCases.append(m_jit.branchPtr(CCallHelpers::NotEqual, scratch1GPR, CCallHelpers::Address(structureGPR, Structure::globalObjectOffset())));
 
@@ -12891,8 +12888,8 @@ void SpeculativeJIT::compileCreateInternalFieldObject(Node* node, Operation oper
     slowCases.append(m_jit.branchTestPtr(MacroAssembler::Zero, rareDataGPR, CCallHelpers::TrustedImm32(JSFunction::rareDataTag)));
     m_jit.loadPtr(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfInternalFunctionAllocationProfile() + InternalFunctionAllocationProfile::offsetOfStructure() - JSFunction::rareDataTag), structureGPR);
     slowCases.append(m_jit.branchTestPtr(CCallHelpers::Zero, structureGPR));
-    m_jit.emitLoadClassInfoFromStructure(structureGPR, scratch1GPR);
-    slowCases.append(m_jit.branchPtr(CCallHelpers::NotEqual, scratch1GPR, TrustedImmPtr(JSClass::info())));
+    m_jit.move(TrustedImmPtr(JSClass::info()), scratch1GPR);
+    slowCases.append(m_jit.branchPtr(CCallHelpers::NotEqual, scratch1GPR, CCallHelpers::Address(structureGPR, Structure::classInfoOffset())));
     m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), globalObject), scratch1GPR);
     slowCases.append(m_jit.branchPtr(CCallHelpers::NotEqual, scratch1GPR, CCallHelpers::Address(structureGPR, Structure::globalObjectOffset())));
 
index 219a4f4..b108abf 100644 (file)
@@ -139,11 +139,11 @@ namespace JSC { namespace FTL {
     macro(StringImpl_data, StringImpl::dataOffset()) \
     macro(StringImpl_hashAndFlags, StringImpl::flagsOffset()) \
     macro(StringImpl_length, StringImpl::lengthMemoryOffset()) \
-    macro(Structure_classInfo, Structure::offsetOfClassInfo()) \
+    macro(Structure_classInfo, Structure::classInfoOffset()) \
     macro(Structure_globalObject, Structure::globalObjectOffset()) \
     macro(Structure_indexingModeIncludingHistory, Structure::indexingModeIncludingHistoryOffset()) \
-    macro(Structure_inlineCapacity, Structure::offsetOfInlineCapacity()) \
-    macro(Structure_cachedPrototypeChainOrRareData, Structure::offsetOfCachedPrototypeChainOrRareData()) \
+    macro(Structure_inlineCapacity, Structure::inlineCapacityOffset()) \
+    macro(Structure_previousOrRareData, Structure::previousOrRareDataOffset()) \
     macro(Structure_prototype, Structure::prototypeOffset()) \
     macro(Structure_structureID, Structure::structureIDOffset()) \
     macro(StructureRareData_cachedOwnKeys, StructureRareData::offsetOfCachedOwnKeys()) \
index d7a81ef..773a006 100644 (file)
@@ -6251,17 +6251,17 @@ private:
 
                 LValue object = lowObject(m_node->child1());
                 LValue structure = loadStructure(object);
-                LValue cachedPrototypeChainOrRareData = loadStructureCachedPrototypeChainOrRareData(structure);
-                m_out.branch(m_out.notNull(cachedPrototypeChainOrRareData), unsure(notNullCase), unsure(slowCase));
+                LValue previousOrRareData = m_out.loadPtr(structure, m_heaps.Structure_previousOrRareData);
+                m_out.branch(m_out.notNull(previousOrRareData), unsure(notNullCase), unsure(slowCase));
 
                 LBasicBlock lastNext = m_out.appendTo(notNullCase, rareDataCase);
                 m_out.branch(
-                    m_out.equal(m_out.load32(cachedPrototypeChainOrRareData, m_heaps.JSCell_structureID), m_out.constInt32(m_graph.m_vm.structureRareDataStructure->structureID())),
+                    m_out.notEqual(m_out.load32(previousOrRareData, m_heaps.JSCell_structureID), m_out.constInt32(m_graph.m_vm.structureStructure->structureID())),
                     unsure(rareDataCase), unsure(slowCase));
 
                 m_out.appendTo(rareDataCase, useCacheCase);
                 ASSERT(bitwise_cast<uintptr_t>(StructureRareData::cachedOwnKeysSentinel()) == 1);
-                LValue cachedOwnKeys = m_out.loadPtr(cachedPrototypeChainOrRareData, m_heaps.StructureRareData_cachedOwnKeys);
+                LValue cachedOwnKeys = m_out.loadPtr(previousOrRareData, m_heaps.StructureRareData_cachedOwnKeys);
                 m_out.branch(m_out.belowOrEqual(cachedOwnKeys, m_out.constIntPtr(bitwise_cast<void*>(StructureRareData::cachedOwnKeysSentinel()))), unsure(slowCase), unsure(useCacheCase));
 
                 m_out.appendTo(useCacheCase, slowButArrayBufferCase);
@@ -6835,8 +6835,7 @@ private:
         m_out.branch(m_out.isZero64(structure), rarely(slowCase), usually(hasStructure));
 
         m_out.appendTo(hasStructure, checkGlobalObjectCase);
-        LValue classInfo = loadStructureClassInfo(structure);
-        m_out.branch(m_out.equal(classInfo, m_out.constIntPtr(m_node->isInternalPromise() ? JSInternalPromise::info() : JSPromise::info())), usually(checkGlobalObjectCase), rarely(slowCase));
+        m_out.branch(m_out.equal(m_out.loadPtr(structure, m_heaps.Structure_classInfo), m_out.constIntPtr(m_node->isInternalPromise() ? JSInternalPromise::info() : JSPromise::info())), usually(checkGlobalObjectCase), rarely(slowCase));
 
         m_out.appendTo(checkGlobalObjectCase, fastAllocationCase);
         ValueFromBlock derivedStructure = m_out.anchor(structure);
@@ -6891,8 +6890,7 @@ private:
         m_out.branch(m_out.isZero64(structure), rarely(slowCase), usually(hasStructure));
 
         m_out.appendTo(hasStructure, checkGlobalObjectCase);
-        LValue classInfo = loadStructureClassInfo(structure);
-        m_out.branch(m_out.equal(classInfo, m_out.constIntPtr(JSClass::info())), usually(checkGlobalObjectCase), rarely(slowCase));
+        m_out.branch(m_out.equal(m_out.loadPtr(structure, m_heaps.Structure_classInfo), m_out.constIntPtr(JSClass::info())), usually(checkGlobalObjectCase), rarely(slowCase));
 
         m_out.appendTo(checkGlobalObjectCase, fastAllocationCase);
         m_out.branch(m_out.equal(m_out.loadPtr(structure, m_heaps.Structure_globalObject), weakPointer(globalObject)), usually(fastAllocationCase), rarely(slowCase));
@@ -13382,7 +13380,7 @@ private:
             LBasicBlock continuation = m_out.newBlock();
 
             LValue structure = loadStructure(cell);
-            LValue classInfo = loadStructureClassInfo(structure);
+            LValue classInfo = m_out.loadPtr(structure, m_heaps.Structure_classInfo);
             ValueFromBlock otherAtStart = m_out.anchor(classInfo);
             m_out.jump(loop);
 
@@ -18398,26 +18396,6 @@ private:
         return m_out.bitXor(encodedStructureBits, entropyBits);
     }
 
-    LValue loadStructureClassInfo(LValue structure)
-    {
-        LValue result = m_out.loadPtr(structure, m_heaps.Structure_classInfo);
-#if CPU(ADDRESS64)
-        return m_out.bitAnd(m_out.constIntPtr(Structure::classInfoMask), result);
-#else
-        return result;
-#endif
-    }
-
-    LValue loadStructureCachedPrototypeChainOrRareData(LValue structure)
-    {
-        LValue result = m_out.loadPtr(structure, m_heaps.Structure_cachedPrototypeChainOrRareData);
-#if CPU(ADDRESS64)
-        return m_out.bitAnd(m_out.constIntPtr(Structure::cachedPrototypeChainOrRareDataMask), result);
-#else
-        return result;
-#endif
-    }
-
     LValue weakPointer(JSCell* pointer)
     {
         addWeakReference(pointer);
index 70f5dd4..e95f8fe 100644 (file)
@@ -1535,14 +1535,6 @@ public:
     
     void emitLoadStructure(VM&, RegisterID source, RegisterID dest, RegisterID scratch);
 
-    void emitLoadClassInfoFromStructure(RegisterID structure, RegisterID dst)
-    {
-        loadPtr(Address(structure, Structure::offsetOfClassInfo()), dst);
-#if CPU(ADDRESS64)
-        andPtr(TrustedImmPtr(bitwise_cast<void*>(Structure::classInfoMask)), dst);
-#endif
-    }
-
     void emitStoreStructureWithTypeInfo(TrustedImmPtr structure, RegisterID dest, RegisterID)
     {
         emitStoreStructureWithTypeInfo(*this, structure, dest);
index c3cbffa..fc94ca3 100644 (file)
@@ -979,7 +979,7 @@ void JIT::emit_op_create_this(const Instruction* currentInstruction)
     JumpList slowCases;
     auto butterfly = TrustedImmPtr(nullptr);
     emitAllocateJSObject(resultReg, JITAllocator::variable(), allocatorReg, structureReg, butterfly, scratchReg, slowCases);
-    load8(Address(structureReg, Structure::offsetOfInlineCapacity()), scratchReg);
+    load8(Address(structureReg, Structure::inlineCapacityOffset()), scratchReg);
     emitInitializeInlineStorage(resultReg, scratchReg);
     addSlowCase(slowCases);
     emitPutVirtualRegister(bytecode.m_dst);
index a8c2036..1c30776 100644 (file)
@@ -1093,7 +1093,7 @@ void JIT::emit_op_create_this(const Instruction* currentInstruction)
     JumpList slowCases;
     auto butterfly = TrustedImmPtr(nullptr);
     emitAllocateJSObject(resultReg, JITAllocator::variable(), allocatorReg, structureReg, butterfly, scratchReg, slowCases);
-    load8(Address(structureReg, Structure::offsetOfInlineCapacity()), scratchReg);
+    load8(Address(structureReg, Structure::inlineCapacityOffset()), scratchReg);
     emitInitializeInlineStorage(resultReg, scratchReg);
     addSlowCase(slowCases);
     emitStoreCell(bytecode.m_dst, resultReg);
index 6417f21..08fabd5 100644 (file)
@@ -618,7 +618,7 @@ static InlineCacheAction tryCachePutByID(JSGlobalObject* globalObject, CodeBlock
                 if (baseValue.asCell()->structure(vm) != newStructure)
                     return GiveUpOnCache;
 
-                ASSERT(newStructure->previousID(vm) == oldStructure);
+                ASSERT(newStructure->previousID() == oldStructure);
                 ASSERT(!newStructure->isDictionary());
                 ASSERT(newStructure->isObject());
                 
@@ -766,7 +766,7 @@ static InlineCacheAction tryCacheDeleteBy(JSGlobalObject* globalObject, CodeBloc
             if (!newStructure->propertyAccessesAreCacheable() || newStructure->isDictionary())
                 return GiveUpOnCache;
             ASSERT(newOffset == slot.cachedOffset());
-            ASSERT(newStructure->previousID(vm) == oldStructure);
+            ASSERT(newStructure->previousID() == oldStructure);
             ASSERT(newStructure->isPropertyDeletionTransition());
             ASSERT(newStructure->isObject());
             ASSERT(isValidOffset(newOffset));
index 2bffc38..3db23ba 100644 (file)
@@ -855,7 +855,7 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_id)
                 Structure* a = vm.heap.structureIDTable().get(oldStructureID);
                 Structure* b = baseValue.asCell()->structure(vm);
                 if (slot.type() == PutPropertySlot::NewProperty)
-                    b = b->previousID(vm);
+                    b = b->previousID();
 
                 if (Structure::shouldConvertToPolyProto(a, b)) {
                     a->rareData()->sharedPolyProtoWatchpoint()->invalidate(vm, StringFireDetail("Detected poly proto opportunity."));
@@ -876,9 +876,9 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_id)
         if (newStructure->propertyAccessesAreCacheable() && baseCell == slot.base()) {
             if (slot.type() == PutPropertySlot::NewProperty) {
                 GCSafeConcurrentJSLocker locker(codeBlock->m_lock, vm.heap);
-                if (!newStructure->isDictionary() && newStructure->previousID(vm)->outOfLineCapacity() == newStructure->outOfLineCapacity()) {
-                    ASSERT(oldStructure == newStructure->previousID(vm));
-                    if (oldStructure == newStructure->previousID(vm)) {
+                if (!newStructure->isDictionary() && newStructure->previousID()->outOfLineCapacity() == newStructure->outOfLineCapacity()) {
+                    ASSERT(oldStructure == newStructure->previousID());
+                    if (oldStructure == newStructure->previousID()) {
                         ASSERT(oldStructure->transitionWatchpointSetHasBeenInvalidated());
 
                         bool sawPolyProto = false;
index 8ddd98a..f6999e7 100644 (file)
@@ -153,7 +153,7 @@ Structure* ClonedArguments::createStructure(VM& vm, JSGlobalObject* globalObject
     Structure* structure = Structure::create(vm, globalObject, prototype, TypeInfo(ClonedArgumentsType, StructureFlags), info(), indexingType);
     structure->addPropertyWithoutTransition(
         vm, vm.propertyNames->length, static_cast<unsigned>(PropertyAttribute::DontEnum),
-        [&](const GCSafeConcurrentJSCellLocker&, PropertyOffset offset, PropertyOffset newMaxOffset) {
+        [&] (const GCSafeConcurrentJSLocker&, PropertyOffset offset, PropertyOffset newMaxOffset) {
             RELEASE_ASSERT(offset == clonedArgumentsLengthPropertyOffset);
             structure->setMaxOffset(vm, newMaxOffset);
         });
index 1d40807..aa273ba 100644 (file)
 namespace JSC {
 
 using ConcurrentJSLock = Lock;
+using ConcurrentJSLockerImpl = LockHolder;
 
-static_assert(sizeof(ConcurrentJSLock) == 1, "Regardless of status of concurrent JS flag, size of ConcurrentJSLock is always one byte.");
+static_assert(sizeof(ConcurrentJSLock) == 1, "Regardless of status of concurrent JS flag, size of ConurrentJSLock is always one byte.");
 
-template<typename Lock>
 class ConcurrentJSLockerBase : public AbstractLocker {
     WTF_MAKE_NONCOPYABLE(ConcurrentJSLockerBase);
 public:
-    explicit ConcurrentJSLockerBase(Lock& lockable)
+    explicit ConcurrentJSLockerBase(ConcurrentJSLock& lockable)
         : m_locker(&lockable)
     {
     }
-    explicit ConcurrentJSLockerBase(Lock* lockable)
+    explicit ConcurrentJSLockerBase(ConcurrentJSLock* lockable)
         : m_locker(lockable)
     {
     }
@@ -64,65 +64,63 @@ public:
     }
 
 private:
-    Locker<Lock> m_locker;
+    ConcurrentJSLockerImpl m_locker;
 };
 
-template<typename Lock>
-class GCSafeConcurrentJSLockerImpl : public ConcurrentJSLockerBase<Lock> {
+class GCSafeConcurrentJSLocker : public ConcurrentJSLockerBase {
 public:
-    GCSafeConcurrentJSLockerImpl(Lock& lockable, Heap& heap)
-        : ConcurrentJSLockerBase<Lock>(lockable)
+    GCSafeConcurrentJSLocker(ConcurrentJSLock& lockable, Heap& heap)
+        : ConcurrentJSLockerBase(lockable)
         , m_deferGC(heap)
     {
     }
 
-    GCSafeConcurrentJSLockerImpl(Lock* lockable, Heap& heap)
-        : ConcurrentJSLockerBase<Lock>(lockable)
+    GCSafeConcurrentJSLocker(ConcurrentJSLock* lockable, Heap& heap)
+        : ConcurrentJSLockerBase(lockable)
         , m_deferGC(heap)
     {
     }
 
-    ~GCSafeConcurrentJSLockerImpl()
+    ~GCSafeConcurrentJSLocker()
     {
         // We have to unlock early due to the destruction order of base
         // vs. derived classes. If we didn't, then we would destroy the 
         // DeferGC object before unlocking the lock which could cause a GC
         // and resulting deadlock.
-        ConcurrentJSLockerBase<Lock>::unlockEarly();
+        unlockEarly();
     }
 
 private:
     DeferGC m_deferGC;
 };
 
-template<typename Lock>
-class ConcurrentJSLockerImpl : public ConcurrentJSLockerBase<Lock> {
+class ConcurrentJSLocker : public ConcurrentJSLockerBase {
 public:
-    ConcurrentJSLockerImpl(Lock& lockable)
-        : ConcurrentJSLockerBase<Lock>(lockable)
+    ConcurrentJSLocker(ConcurrentJSLock& lockable)
+        : ConcurrentJSLockerBase(lockable)
 #if !defined(NDEBUG)
         , m_disallowGC(std::in_place)
 #endif
     {
     }
 
-    ConcurrentJSLockerImpl(Lock* lockable)
-        : ConcurrentJSLockerBase<Lock>(lockable)
+    ConcurrentJSLocker(ConcurrentJSLock* lockable)
+        : ConcurrentJSLockerBase(lockable)
 #if !defined(NDEBUG)
         , m_disallowGC(std::in_place)
 #endif
     {
     }
 
-    ConcurrentJSLockerImpl(NoLockingNecessaryTag)
-        : ConcurrentJSLockerBase<Lock>(NoLockingNecessary)
+    ConcurrentJSLocker(NoLockingNecessaryTag)
+        : ConcurrentJSLockerBase(NoLockingNecessary)
 #if !defined(NDEBUG)
         , m_disallowGC(WTF::nullopt)
 #endif
     {
     }
     
-    ConcurrentJSLockerImpl(int) = delete;
+    ConcurrentJSLocker(int) = delete;
 
 #if !defined(NDEBUG)
 private:
@@ -130,7 +128,4 @@ private:
 #endif
 };
 
-using ConcurrentJSLocker = ConcurrentJSLockerImpl<ConcurrentJSLock>;
-using GCSafeConcurrentJSLocker = GCSafeConcurrentJSLockerImpl<ConcurrentJSLock>;
-
 } // namespace JSC
index 9e677ea..2bef4a7 100644 (file)
@@ -24,7 +24,6 @@
 
 #include "CallData.h"
 #include "CellState.h"
-#include "ConcurrentJSLock.h"
 #include "ConstructData.h"
 #include "EnumerationMode.h"
 #include "Heap.h"
@@ -290,9 +289,6 @@ private:
     JS_EXPORT_PRIVATE void unlockSlow();
 };
 
-using ConcurrentJSCellLocker = ConcurrentJSLockerImpl<JSCellLock>;
-using GCSafeConcurrentJSCellLocker = GCSafeConcurrentJSLockerImpl<JSCellLock>;
-
 // FIXME: Refer to Subspace by reference.
 // https://bugs.webkit.org/show_bug.cgi?id=166988
 template<typename Type>
index 25dff53..5208acd 100644 (file)
@@ -2007,7 +2007,7 @@ bool JSObject::deleteProperty(JSCell* cell, JSGlobalObject* globalObject, Proper
 
         PropertyOffset offset = invalidOffset;
         if (structure->isUncacheableDictionary())
-            offset = structure->removePropertyWithoutTransition(vm, propertyName, [](const GCSafeConcurrentJSCellLocker&, PropertyOffset, PropertyOffset) { });
+            offset = structure->removePropertyWithoutTransition(vm, propertyName, [] (const GCSafeConcurrentJSLocker&, PropertyOffset, PropertyOffset) { });
         else {
             structure = Structure::removePropertyTransition(vm, structure, propertyName, offset, &deferredWatchpointFire);
             slot.setHit(offset);
@@ -3776,7 +3776,7 @@ void JSObject::convertToDictionary(VM& vm)
         vm, Structure::toCacheableDictionaryTransition(vm, structure(vm), &deferredWatchpointFire));
 }
 
-void JSObject::shiftButterflyAfterFlattening(const GCSafeConcurrentJSCellLocker&, VM& vm, Structure* structure, size_t outOfLineCapacityAfter)
+void JSObject::shiftButterflyAfterFlattening(const GCSafeConcurrentJSLocker&, VM& vm, Structure* structure, size_t outOfLineCapacityAfter)
 {
     // This could interleave visitChildren because some old structure could have been a non
     // dictionary structure. We have to be crazy careful. But, we are guaranteed to be holding
index 8b60471..1fd12b0 100644 (file)
@@ -810,7 +810,7 @@ public:
     {
         structure(vm)->flattenDictionaryStructure(vm, this);
     }
-    void shiftButterflyAfterFlattening(const GCSafeConcurrentJSCellLocker&, VM&, Structure*, size_t outOfLineCapacityAfter);
+    void shiftButterflyAfterFlattening(const GCSafeConcurrentJSLocker&, VM&, Structure* structure, size_t outOfLineCapacityAfter);
 
     JSGlobalObject* globalObject() const
     {
@@ -1326,7 +1326,7 @@ inline JSValue JSObject::getPrototype(VM& vm, JSGlobalObject* globalObject)
 // flatten an object.
 inline JSValue JSObject::getDirectConcurrently(Structure* structure, PropertyOffset offset) const
 {
-    ConcurrentJSCellLocker locker(structure->cellLock());
+    ConcurrentJSLocker locker(structure->lock());
     if (!structure->isValidOffset(offset))
         return { };
     return getDirect(offset);
index 5fb8458..51e0bf3 100644 (file)
@@ -216,7 +216,7 @@ ALWAYS_INLINE PropertyOffset JSObject::prepareToPutDirectWithoutTransition(VM& v
     PropertyOffset result;
     structure->addPropertyWithoutTransition(
         vm, propertyName, attributes,
-        [&](const GCSafeConcurrentJSCellLocker&, PropertyOffset offset, PropertyOffset newMaxOffset) {
+        [&] (const GCSafeConcurrentJSLocker&, PropertyOffset offset, PropertyOffset newMaxOffset) {
             unsigned newOutOfLineCapacity = Structure::outOfLineCapacity(newMaxOffset);
             if (newOutOfLineCapacity != oldOutOfLineCapacity) {
                 Butterfly* butterfly = allocateMoreOutOfLineStorage(vm, oldOutOfLineCapacity, newOutOfLineCapacity);
index a1337c6..b02b347 100644 (file)
@@ -44,7 +44,6 @@ void printInternal(PrintStream& out, JSC::JSType type)
     CASE(StringType)
     CASE(SymbolType)
     CASE(BigIntType)
-    CASE(StructureRareDataType)
     CASE(CustomGetterSetterType)
     CASE(APIValueWrapperType)
     CASE(NativeExecutableType)
index 0f868a6..4836f91 100644 (file)
@@ -30,7 +30,6 @@ enum JSType : uint8_t {
     LastMaybeFalsyCellPrimitive = BigIntType,
     SymbolType,
 
-    StructureRareDataType,
     GetterSetterType,
     CustomGetterSetterType,
     APIValueWrapperType,
index 832ce44..764ad06 100644 (file)
@@ -91,7 +91,7 @@ bool StructureTransitionTable::contains(UniquedStringImpl* rep, unsigned attribu
 {
     if (isUsingSingleSlot()) {
         Structure* transition = singleTransition();
-        return transition && transition->transitionPropertyName() == rep && transition->transitionPropertyAttributes() == attributes && transition->isPropertyDeletionTransition() == !isAddition;
+        return transition && transition->m_transitionPropertyName == rep && transition->transitionPropertyAttributes() == attributes && transition->isPropertyDeletionTransition() == !isAddition;
     }
     return map()->get(StructureTransitionTable::Hash::Key(rep, attributes, isAddition));
 }
@@ -100,7 +100,7 @@ inline Structure* StructureTransitionTable::get(UniquedStringImpl* rep, unsigned
 {
     if (isUsingSingleSlot()) {
         Structure* transition = singleTransition();
-        return (transition && transition->transitionPropertyName() == rep && transition->transitionPropertyAttributes() == attributes && transition->isPropertyDeletionTransition() == !isAddition) ? transition : nullptr;
+        return (transition && transition->m_transitionPropertyName == rep && transition->transitionPropertyAttributes() == attributes && transition->isPropertyDeletionTransition() == !isAddition) ? transition : 0;
     }
     return map()->get(StructureTransitionTable::Hash::Key(rep, attributes, isAddition));
 }
@@ -123,7 +123,7 @@ void StructureTransitionTable::add(VM& vm, Structure* structure)
     }
 
     // Add the structure to the map.
-    map()->set(StructureTransitionTable::Hash::Key(structure->transitionPropertyName(), structure->transitionPropertyAttributes(), !structure->isPropertyDeletionTransition()), structure);
+    map()->set(StructureTransitionTable::Hash::Key(structure->m_transitionPropertyName.get(), structure->transitionPropertyAttributes(), !structure->isPropertyDeletionTransition()), structure);
 }
 
 void Structure::dumpStatistics()
@@ -142,7 +142,7 @@ void Structure::dumpStatistics()
         switch (structure->m_transitionTable.size()) {
             case 0:
                 ++numberLeaf;
-                if (!structure->previousID(structure->vm()))
+                if (!structure->previousID())
                     ++numberSingletons;
                 break;
 
@@ -151,7 +151,7 @@ void Structure::dumpStatistics()
                 break;
         }
 
-        if (PropertyTable* table = structure->propertyTableUnsafeOrNull()) {
+        if (PropertyTable* table = structure->propertyTableOrNull()) {
             ++numberWithPropertyMaps;
             totalPropertyMapsSize += table->sizeInMemory();
         }
@@ -174,12 +174,15 @@ void Structure::dumpStatistics()
 Structure::Structure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingType, unsigned inlineCapacity)
     : JSCell(vm, vm.structureStructure.get())
     , m_blob(vm.heap.structureIDTable().allocateID(this), indexingType, typeInfo)
+    , m_outOfLineTypeFlags(typeInfo.outOfLineTypeFlags())
+    , m_inlineCapacity(inlineCapacity)
+    , m_bitField(0)
     , m_globalObject(vm, this, globalObject, WriteBarrier<JSGlobalObject>::MayBeNull)
     , m_prototype(vm, this, prototype)
+    , m_classInfo(classInfo)
     , m_transitionWatchpointSet(IsWatched)
+    , m_propertyHash(0)
 {
-    setInlineCapacity(inlineCapacity);
-    setClassInfo(classInfo);
     setDictionaryKind(NoneDictionaryKind);
     setIsPinnedPropertyTable(false);
     setHasGetterSetterProperties(classInfo->hasStaticSetterOrReadonlyProperties());
@@ -197,30 +200,31 @@ Structure::Structure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, co
     setIsPropertyDeletionTransition(false);
     setTransitionOffset(vm, invalidOffset);
     setMaxOffset(vm, invalidOffset);
-    setOutOfLineTypeFlags(typeInfo.outOfLineTypeFlags());
-
     ASSERT(inlineCapacity <= JSFinalObject::maxInlineCapacity());
     ASSERT(static_cast<PropertyOffset>(inlineCapacity) < firstOutOfLineOffset);
     ASSERT(!hasRareData());
-    ASSERT(hasReadOnlyOrGetterSetterPropertiesExcludingProto() || !this->classInfo()->hasStaticSetterOrReadonlyProperties());
-    ASSERT(hasGetterSetterProperties() || !this->classInfo()->hasStaticSetterOrReadonlyProperties());
-    ASSERT(!this->typeInfo().overridesGetCallData() || this->classInfo()->methodTable.getCallData != &JSCell::getCallData);
+    ASSERT(hasReadOnlyOrGetterSetterPropertiesExcludingProto() || !m_classInfo->hasStaticSetterOrReadonlyProperties());
+    ASSERT(hasGetterSetterProperties() || !m_classInfo->hasStaticSetterOrReadonlyProperties());
+    ASSERT(!this->typeInfo().overridesGetCallData() || m_classInfo->methodTable.getCallData != &JSCell::getCallData);
 }
 
 const ClassInfo Structure::s_info = { "Structure", nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(Structure) };
 
 Structure::Structure(VM& vm)
     : JSCell(CreatingEarlyCell)
+    , m_inlineCapacity(0)
+    , m_bitField(0)
     , m_prototype(vm, this, jsNull())
+    , m_classInfo(info())
     , m_transitionWatchpointSet(IsWatched)
+    , m_propertyHash(0)
 {
-    setInlineCapacity(0);
-    setClassInfo(info());
     setDictionaryKind(NoneDictionaryKind);
     setIsPinnedPropertyTable(false);
-    setHasGetterSetterProperties(classInfo()->hasStaticSetterOrReadonlyProperties());
+    setHasGetterSetterProperties(m_classInfo->hasStaticSetterOrReadonlyProperties());
     setHasCustomGetterSetterProperties(false);
-    setHasReadOnlyOrGetterSetterPropertiesExcludingProto(classInfo()->hasStaticSetterOrReadonlyProperties());
+    setHasReadOnlyOrGetterSetterPropertiesExcludingProto(m_classInfo->hasStaticSetterOrReadonlyProperties());
     setHasUnderscoreProtoPropertyExcludingOriginalProto(false);
     setIsQuickPropertyAccessAllowedForEnumeration(true);
     setTransitionPropertyAttributes(0);
@@ -236,26 +240,23 @@ Structure::Structure(VM& vm)
  
     TypeInfo typeInfo = TypeInfo(CellType, StructureFlags);
     m_blob = StructureIDBlob(vm.heap.structureIDTable().allocateID(this), 0, typeInfo);
-    setOutOfLineTypeFlags(typeInfo.outOfLineTypeFlags());
+    m_outOfLineTypeFlags = typeInfo.outOfLineTypeFlags();
 
-    ASSERT(hasReadOnlyOrGetterSetterPropertiesExcludingProto() || !classInfo()->hasStaticSetterOrReadonlyProperties());
-    ASSERT(hasGetterSetterProperties() || !classInfo()->hasStaticSetterOrReadonlyProperties());
-    ASSERT(!this->typeInfo().overridesGetCallData() || classInfo()->methodTable.getCallData != &JSCell::getCallData);
+    ASSERT(hasReadOnlyOrGetterSetterPropertiesExcludingProto() || !m_classInfo->hasStaticSetterOrReadonlyProperties());
+    ASSERT(hasGetterSetterProperties() || !m_classInfo->hasStaticSetterOrReadonlyProperties());
+    ASSERT(!this->typeInfo().overridesGetCallData() || m_classInfo->methodTable.getCallData != &JSCell::getCallData);
 }
 
 Structure::Structure(VM& vm, Structure* previous, DeferredStructureTransitionWatchpointFire* deferred)
     : JSCell(vm, vm.structureStructure.get())
-#if CPU(ADDRESS64)
-    , m_propertyHashAndSeenProperties(previous->m_propertyHashAndSeenProperties)
-#else
-    , m_propertyHash(previous->m_propertyHash)
-    , m_seenProperties(previous->m_seenProperties)
-#endif
+    , m_inlineCapacity(previous->m_inlineCapacity)
+    , m_bitField(0)
     , m_prototype(vm, this, previous->m_prototype.get())
+    , m_classInfo(previous->m_classInfo)
     , m_transitionWatchpointSet(IsWatched)
+    , m_propertyHash(previous->m_propertyHash)
+    , m_seenProperties(previous->m_seenProperties)
 {
-    setInlineCapacity(previous->inlineCapacity());
-    setClassInfo(previous->classInfo());
     setDictionaryKind(previous->dictionaryKind());
     setIsPinnedPropertyTable(false);
     setHasBeenFlattenedBefore(previous->hasBeenFlattenedBefore());
@@ -276,7 +277,7 @@ Structure::Structure(VM& vm, Structure* previous, DeferredStructureTransitionWat
  
     TypeInfo typeInfo = previous->typeInfo();
     m_blob = StructureIDBlob(vm.heap.structureIDTable().allocateID(this), previous->indexingModeIncludingHistory(), typeInfo);
-    setOutOfLineTypeFlags(typeInfo.outOfLineTypeFlags());
+    m_outOfLineTypeFlags = typeInfo.outOfLineTypeFlags();
 
     ASSERT(!previous->typeInfo().structureIsImmortal());
     setPreviousID(vm, previous);
@@ -288,9 +289,9 @@ Structure::Structure(VM& vm, Structure* previous, DeferredStructureTransitionWat
 
     if (previous->m_globalObject)
         m_globalObject.set(vm, this, previous->m_globalObject.get());
-    ASSERT(hasReadOnlyOrGetterSetterPropertiesExcludingProto() || !classInfo()->hasStaticSetterOrReadonlyProperties());
-    ASSERT(hasGetterSetterProperties() || !classInfo()->hasStaticSetterOrReadonlyProperties());
-    ASSERT(!this->typeInfo().overridesGetCallData() || classInfo()->methodTable.getCallData != &JSCell::getCallData);
+    ASSERT(hasReadOnlyOrGetterSetterPropertiesExcludingProto() || !m_classInfo->hasStaticSetterOrReadonlyProperties());
+    ASSERT(hasGetterSetterProperties() || !m_classInfo->hasStaticSetterOrReadonlyProperties());
+    ASSERT(!this->typeInfo().overridesGetCallData() || m_classInfo->methodTable.getCallData != &JSCell::getCallData);
 }
 
 Structure::~Structure()
@@ -312,7 +313,7 @@ Structure* Structure::create(PolyProtoTag, VM& vm, JSGlobalObject* globalObject,
     unsigned oldOutOfLineCapacity = result->outOfLineCapacity();
     result->addPropertyWithoutTransition(
         vm, vm.propertyNames->builtinNames().polyProtoName(), static_cast<unsigned>(PropertyAttribute::DontEnum),
-        [&](const GCSafeConcurrentJSCellLocker&, PropertyOffset offset, PropertyOffset newMaxOffset) {
+        [&] (const GCSafeConcurrentJSLocker&, PropertyOffset offset, PropertyOffset newMaxOffset) {
             RELEASE_ASSERT(Structure::outOfLineCapacity(newMaxOffset) == oldOutOfLineCapacity);
             RELEASE_ASSERT(offset == knownPolyProtoOffset);
             RELEASE_ASSERT(isInlineOffset(knownPolyProtoOffset));
@@ -328,15 +329,15 @@ bool Structure::isValidPrototype(JSValue prototype)
     return prototype.isNull() || (prototype.isObject() && prototype.getObject()->mayBePrototype());
 }
 
-void Structure::findStructuresAndMapForMaterialization(VM& vm, Vector<Structure*, 8>& structures, Structure*& structure, PropertyTable*& table)
+void Structure::findStructuresAndMapForMaterialization(Vector<Structure*, 8>& structures, Structure*& structure, PropertyTable*& table)
 {
     ASSERT(structures.isEmpty());
-    table = nullptr;
+    table = 0;
 
-    for (structure = this; structure; structure = structure->previousID(vm)) {
-        structure->cellLock().lock();
+    for (structure = this; structure; structure = structure->previousID()) {
+        structure->m_lock.lock();
         
-        table = structure->propertyTableUnsafeOrNull();
+        table = structure->propertyTableOrNull();
         if (table) {
             // Leave the structure locked, so that the caller can do things to it atomically
             // before it loses its property table.
@@ -344,7 +345,7 @@ void Structure::findStructuresAndMapForMaterialization(VM& vm, Vector<Structure*
         }
         
         structures.append(structure);
-        structure->cellLock().unlock();
+        structure->m_lock.unlock();
     }
     
     ASSERT(!structure);
@@ -362,35 +363,34 @@ PropertyTable* Structure::materializePropertyTable(VM& vm, bool setPropertyTable
     Structure* structure;
     PropertyTable* table;
     
-    findStructuresAndMapForMaterialization(vm, structures, structure, table);
+    findStructuresAndMapForMaterialization(structures, structure, table);
     
-    unsigned capacity = numberOfSlotsForMaxOffset(maxOffset(), inlineCapacity());
+    unsigned capacity = numberOfSlotsForMaxOffset(maxOffset(), m_inlineCapacity);
     if (table) {
         table = table->copy(vm, capacity);
-        structure->cellLock().unlock();
+        structure->m_lock.unlock();
     } else
         table = PropertyTable::create(vm, capacity);
     
     // Must hold the lock on this structure, since we will be modifying this structure's
     // property map. We don't want getConcurrently() to see the property map in a half-baked
     // state.
-    GCSafeConcurrentJSCellLocker locker(cellLock(), vm.heap);
+    GCSafeConcurrentJSLocker locker(m_lock, vm.heap);
     if (setPropertyTable)
         this->setPropertyTable(vm, table);
 
     for (size_t i = structures.size(); i--;) {
         structure = structures[i];
-        UniquedStringImpl* transitionPropertyName = structure->transitionPropertyName();
-        if (!transitionPropertyName)
+        if (!structure->m_transitionPropertyName)
             continue;
         if (structure->isPropertyDeletionTransition()) {
-            auto item = table->find(transitionPropertyName);
+            auto item = table->find(structure->m_transitionPropertyName.get());
             ASSERT(item.first);
             table->remove(item);
             table->addDeletedOffset(structure->transitionOffset());
             continue;
         }
-        PropertyMapEntry entry(transitionPropertyName, structure->transitionOffset(), structure->transitionPropertyAttributes());
+        PropertyMapEntry entry(structure->m_transitionPropertyName.get(), structure->transitionOffset(), structure->transitionPropertyAttributes());
         auto nextOffset = table->nextOffset(structure->inlineCapacity());
         ASSERT_UNUSED(nextOffset, nextOffset == structure->transitionOffset());
         auto result = table->add(entry);
@@ -425,7 +425,7 @@ Structure* Structure::addPropertyTransitionToExistingStructureImpl(Structure* st
         return existingTransition;
     }
 
-    return nullptr;
+    return 0;
 }
 
 Structure* Structure::addPropertyTransitionToExistingStructure(Structure* structure, PropertyName propertyName, unsigned attributes, PropertyOffset& offset)
@@ -436,7 +436,7 @@ Structure* Structure::addPropertyTransitionToExistingStructure(Structure* struct
 
 Structure* Structure::addPropertyTransitionToExistingStructureConcurrently(Structure* structure, UniquedStringImpl* uid, unsigned attributes, PropertyOffset& offset)
 {
-    ConcurrentJSCellLocker locker(structure->cellLock());
+    ConcurrentJSLocker locker(structure->m_lock);
     return addPropertyTransitionToExistingStructureImpl(structure, uid, attributes, offset);
 }
 
@@ -497,7 +497,8 @@ Structure* Structure::addNewPropertyTransition(VM& vm, Structure* structure, Pro
     }
     
     Structure* transition = create(vm, structure, deferred);
-    transition->setCachedPrototypeChain(vm, structure->cachedPrototypeChain());
+
+    transition->m_cachedPrototypeChain.setMayBeNull(vm, transition, structure->m_cachedPrototypeChain.get());
     
     // While we are adding the property, rematerializing the property table is super weird: we already
     // have a m_transitionPropertyName and transitionPropertyAttributes but the m_transitionOffset is still wrong. If the
@@ -509,12 +510,12 @@ Structure* Structure::addNewPropertyTransition(VM& vm, Structure* structure, Pro
     // case all is well.  If it wasn't for the lock, the GC would have TOCTOU: if could read
     // protectPropertyTableWhileTransitioning before we set it to true, and then blow the table away after.
     {
-        ConcurrentJSCellLocker locker(transition->cellLock());
+        ConcurrentJSLocker locker(transition->m_lock);
         transition->setProtectPropertyTableWhileTransitioning(true);
-        transition->setTransitionPropertyName(locker, propertyName.uid());
     }
 
     transition->m_blob.setIndexingModeIncludingHistory(structure->indexingModeIncludingHistory() & ~CopyOnWrite);
+    transition->m_transitionPropertyName = propertyName.uid();
     transition->setTransitionPropertyAttributes(attributes);
     transition->setPropertyTable(vm, structure->takePropertyTableOrCloneIfPinned(vm));
     transition->setMaxOffset(vm, structure->maxOffset());
@@ -529,7 +530,7 @@ Structure* Structure::addNewPropertyTransition(VM& vm, Structure* structure, Pro
 
     checkOffset(transition->transitionOffset(), transition->inlineCapacity());
     {
-        GCSafeConcurrentJSCellLocker locker(structure->cellLock(), vm.heap);
+        GCSafeConcurrentJSLocker locker(structure->m_lock, vm.heap);
         structure->m_transitionTable.add(vm, transition);
     }
     transition->checkOffsetConsistency();
@@ -577,7 +578,7 @@ Structure* Structure::removePropertyTransitionFromExistingStructureConcurrently(
     unsigned attributes = 0;
     if (structure->getConcurrently(propertyName.uid(), attributes) == invalidOffset)
         return nullptr;
-    ConcurrentJSCellLocker locker(structure->cellLock());
+    ConcurrentJSLocker locker(structure->m_lock);
     return removePropertyTransitionFromExistingStructureImpl(structure, propertyName, attributes, offset);
 }
 
@@ -590,7 +591,7 @@ Structure* Structure::removeNewPropertyTransition(VM& vm, Structure* structure,
     ASSERT(structure->getConcurrently(propertyName.uid()) != invalidOffset);
 
     int transitionCount = 0;
-    for (auto* s = structure; s && transitionCount <= s_maxTransitionLength; s = s->previousID(vm))
+    for (auto* s = structure; s && transitionCount <= s_maxTransitionLength; s = s->previousID())
         ++transitionCount;
 
     if (transitionCount > s_maxTransitionLength) {
@@ -602,16 +603,16 @@ Structure* Structure::removeNewPropertyTransition(VM& vm, Structure* structure,
     }
 
     Structure* transition = create(vm, structure, deferred);
-    transition->setCachedPrototypeChain(vm, structure->cachedPrototypeChain());
+    transition->m_cachedPrototypeChain.setMayBeNull(vm, transition, structure->m_cachedPrototypeChain.get());
 
     // While we are deleting the property, we need to make sure the table is not cleared.
     {
-        ConcurrentJSCellLocker locker(transition->cellLock());
+        ConcurrentJSLocker locker(transition->m_lock);
         transition->setProtectPropertyTableWhileTransitioning(true);
-        transition->setTransitionPropertyName(locker, propertyName.uid());
     }
 
     transition->m_blob.setIndexingModeIncludingHistory(structure->indexingModeIncludingHistory() & ~CopyOnWrite);
+    transition->m_transitionPropertyName = propertyName.uid();
     transition->setPropertyTable(vm, structure->takePropertyTableOrCloneIfPinned(vm));
     transition->setMaxOffset(vm, structure->maxOffset());
     transition->setIsPropertyDeletionTransition(true);
@@ -627,7 +628,7 @@ Structure* Structure::removeNewPropertyTransition(VM& vm, Structure* structure,
 
     checkOffset(transition->transitionOffset(), transition->inlineCapacity());
     {
-        GCSafeConcurrentJSCellLocker locker(structure->cellLock(), vm.heap);
+        GCSafeConcurrentJSLocker locker(structure->m_lock, vm.heap);
         structure->m_transitionTable.add(vm, transition);
     }
     transition->checkOffsetConsistency();
@@ -645,7 +646,7 @@ Structure* Structure::changePrototypeTransition(VM& vm, Structure* structure, JS
     transition->m_prototype.set(vm, transition, prototype);
 
     PropertyTable* table = structure->copyPropertyTableForPinning(vm);
-    transition->pin(holdLock(transition->cellLock()), vm, table);
+    transition->pin(holdLock(transition->m_lock), vm, table);
     transition->setMaxOffset(vm, structure->maxOffset());
     
     transition->checkOffsetConsistency();
@@ -658,7 +659,7 @@ Structure* Structure::attributeChangeTransition(VM& vm, Structure* structure, Pr
         Structure* transition = create(vm, structure);
 
         PropertyTable* table = structure->copyPropertyTableForPinning(vm);
-        transition->pin(holdLock(transition->cellLock()), vm, table);
+        transition->pin(holdLock(transition->m_lock), vm, table);
         transition->setMaxOffset(vm, structure->maxOffset());
         
         structure = transition;
@@ -680,7 +681,7 @@ Structure* Structure::toDictionaryTransition(VM& vm, Structure* structure, Dicti
     Structure* transition = create(vm, structure, deferred);
 
     PropertyTable* table = structure->copyPropertyTableForPinning(vm);
-    transition->pin(holdLock(transition->cellLock()), vm, table);
+    transition->pin(holdLock(transition->m_lock), vm, table);
     transition->setMaxOffset(vm, structure->maxOffset());
     transition->setDictionaryKind(kind);
     transition->setHasBeenDictionary(true);
@@ -716,12 +717,12 @@ Structure* Structure::preventExtensionsTransition(VM& vm, Structure* structure)
 
 PropertyTable* Structure::takePropertyTableOrCloneIfPinned(VM& vm)
 {
-    // This function must always return a property table. It can't return null.
-    PropertyTable* result = propertyTableUnsafeOrNull();
+    // This must always return a property table. It can't return null.
+    PropertyTable* result = propertyTableOrNull();
     if (result) {
         if (isPinnedPropertyTable())
             return result->copy(vm, result->size() + 1);
-        ConcurrentJSCellLocker locker(cellLock());
+        ConcurrentJSLocker locker(m_lock);
         setPropertyTable(vm, nullptr);
         return result;
     }
@@ -758,10 +759,10 @@ Structure* Structure::nonPropertyTransitionSlow(VM& vm, Structure* structure, No
         // table doesn't know how to take into account such wholesale edits.
 
         PropertyTable* table = structure->copyPropertyTableForPinning(vm);
-        transition->pinForCaching(holdLock(transition->cellLock()), vm, table);
+        transition->pinForCaching(holdLock(transition->m_lock), vm, table);
         transition->setMaxOffset(vm, structure->maxOffset());
         
-        table = transition->propertyTableUnsafeOrNull();
+        table = transition->propertyTableOrNull();
         RELEASE_ASSERT(table);
         for (auto& entry : *table) {
             if (setsDontDeleteOnAllProperties(transitionKind))
@@ -776,14 +777,14 @@ Structure* Structure::nonPropertyTransitionSlow(VM& vm, Structure* structure, No
     }
     
     if (setsReadOnlyOnNonAccessorProperties(transitionKind)
-        && !transition->propertyTableUnsafeOrNull()->isEmpty())
+        && !transition->propertyTableOrNull()->isEmpty())
         transition->setHasReadOnlyOrGetterSetterPropertiesExcludingProto(true);
     
     if (structure->isDictionary()) {
         PropertyTable* table = transition->ensurePropertyTable(vm);
-        transition->pin(holdLock(transition->cellLock()), vm, table);
+        transition->pin(holdLock(transition->m_lock), vm, table);
     } else {
-        auto locker = holdLock(structure->cellLock());
+        auto locker = holdLock(structure->m_lock);
         structure->m_transitionTable.add(vm, transition);
     }
 
@@ -835,14 +836,14 @@ Structure* Structure::flattenDictionaryStructure(VM& vm, JSObject* object)
     ASSERT(isDictionary());
     ASSERT(object->structure(vm) == this);
     
-    GCSafeConcurrentJSCellLocker locker(cellLock(), vm.heap);
+    GCSafeConcurrentJSLocker locker(m_lock, vm.heap);
     
     object->setStructureIDDirectly(nuke(id()));
     WTF::storeStoreFence();
 
     size_t beforeOutOfLineCapacity = this->outOfLineCapacity();
     if (isUncacheableDictionary()) {
-        PropertyTable* table = propertyTableUnsafeOrNull();
+        PropertyTable* table = propertyTableOrNull();
         ASSERT(table);
 
         size_t propertyCount = table->size();
@@ -856,14 +857,14 @@ Structure* Structure::flattenDictionaryStructure(VM& vm, JSObject* object)
         auto offset = invalidOffset;
         for (PropertyTable::iterator iter = table->begin(); iter != end; ++iter, ++i) {
             values[i] = object->getDirect(iter->offset);
-            offset = iter->offset = offsetForPropertyNumber(i, inlineCapacity());
+            offset = iter->offset = offsetForPropertyNumber(i, m_inlineCapacity);
         }
         setMaxOffset(vm, offset);
         ASSERT(transitionOffset() == invalidOffset);
         
         // Copies in our values to their compacted locations.
         for (unsigned i = 0; i < propertyCount; i++)
-            object->putDirect(vm, offsetForPropertyNumber(i, inlineCapacity()), values[i]);
+            object->putDirect(vm, offsetForPropertyNumber(i, m_inlineCapacity), values[i]);
 
         table->clearDeletedOffsets();
 
@@ -909,32 +910,27 @@ Structure* Structure::flattenDictionaryStructure(VM& vm, JSObject* object)
     return this;
 }
 
-void Structure::pin(const AbstractLocker& locker, VM& vm, PropertyTable* table)
+void Structure::pin(const AbstractLocker&, VM& vm, PropertyTable* table)
 {
     setIsPinnedPropertyTable(true);
     setPropertyTable(vm, table);
     clearPreviousID();
-    setTransitionPropertyName(locker, nullptr);
+    m_transitionPropertyName = nullptr;
 }
 
-void Structure::pinForCaching(const AbstractLocker& locker, VM& vm, PropertyTable* table)
+void Structure::pinForCaching(const AbstractLocker&, VM& vm, PropertyTable* table)
 {
     setIsPinnedPropertyTable(true);
     setPropertyTable(vm, table);
-    setTransitionPropertyName(locker, nullptr);
+    m_transitionPropertyName = nullptr;
 }
 
 void Structure::allocateRareData(VM& vm)
 {
     ASSERT(!hasRareData());
-    StructureRareData* rareData = StructureRareData::create(vm, cachedPrototypeChain());
+    StructureRareData* rareData = StructureRareData::create(vm, previousID());
     WTF::storeStoreFence();
-#if CPU(ADDRESS64)
-    m_inlineCapacityAndCachedPrototypeChainOrRareData.setPointer(rareData);
-    vm.heap.writeBarrier(this, rareData);
-#else
-    m_cachedPrototypeChainOrRareData.set(vm, this, rareData);
-#endif
+    m_previousOrRareData.set(vm, this, rareData);
     ASSERT(hasRareData());
 }
 
@@ -948,7 +944,7 @@ WatchpointSet* Structure::ensurePropertyReplacementWatchpointSet(VM& vm, Propert
     
     if (!hasRareData())
         allocateRareData(vm);
-    ConcurrentJSCellLocker locker(cellLock());
+    ConcurrentJSLocker locker(m_lock);
     StructureRareData* rareData = this->rareData();
     if (!rareData->m_replacementWatchpointSets) {
         rareData->m_replacementWatchpointSets =
@@ -1018,7 +1014,7 @@ PropertyMapStatisticsExitLogger::~PropertyMapStatisticsExitLogger()
 
 PropertyTable* Structure::copyPropertyTableForPinning(VM& vm)
 {
-    if (PropertyTable* table = propertyTableUnsafeOrNull())
+    if (PropertyTable* table = propertyTableOrNull())
         return PropertyTable::clone(vm, *table);
     bool setPropertyTable = false;
     return materializePropertyTable(vm, setPropertyTable);
@@ -1058,14 +1054,14 @@ PropertyOffset Structure::add(VM& vm, PropertyName propertyName, unsigned attrib
 {
     return add<ShouldPin::No>(
         vm, propertyName, attributes,
-        [this, &vm](const GCSafeConcurrentJSCellLocker&, PropertyOffset, PropertyOffset newMaxOffset) {
+        [this, &vm] (const GCSafeConcurrentJSLocker&, PropertyOffset, PropertyOffset newMaxOffset) {
             setMaxOffset(vm, newMaxOffset);
         });
 }
 
 PropertyOffset Structure::remove(VM& vm, PropertyName propertyName)
 {
-    return remove<ShouldPin::No>(vm, propertyName, [this, &vm](const GCSafeConcurrentJSCellLocker&, PropertyOffset, PropertyOffset newMaxOffset) {
+    return remove<ShouldPin::No>(vm, propertyName, [this, &vm] (const GCSafeConcurrentJSLocker&, PropertyOffset, PropertyOffset newMaxOffset) {
         setMaxOffset(vm, newMaxOffset);
     });
 }
@@ -1136,21 +1132,25 @@ void Structure::visitChildren(JSCell* cell, SlotVisitor& visitor)
 
     Base::visitChildren(thisObject, visitor);
     
-    ConcurrentJSCellLocker locker(thisObject->cellLock());
+    ConcurrentJSLocker locker(thisObject->m_lock);
     
     visitor.append(thisObject->m_globalObject);
-    visitor.append(thisObject->m_prototype);
-    visitor.appendUnbarriered(thisObject->previousID(visitor.vm()));
-    visitor.appendUnbarriered(thisObject->cachedPrototypeChainOrRareData());
+    if (!thisObject->isObject())
+        thisObject->m_cachedPrototypeChain.clear();
+    else {
+        visitor.append(thisObject->m_prototype);
+        visitor.append(thisObject->m_cachedPrototypeChain);
+    }
+    visitor.append(thisObject->m_previousOrRareData);
 
     if (thisObject->isPinnedPropertyTable() || thisObject->protectPropertyTableWhileTransitioning()) {
         // NOTE: This can interleave in pin(), in which case it may see a null property table.
         // That's fine, because then the barrier will fire and we will scan this again.
-        visitor.appendUnbarriered(thisObject->propertyTableUnsafeOrNull());
+        visitor.append(thisObject->m_propertyTableUnsafe);
     } else if (visitor.isAnalyzingHeap())
-        visitor.appendUnbarriered(thisObject->propertyTableUnsafeOrNull());
-    else if (thisObject->propertyTableUnsafeOrNull())
-        thisObject->clearPropertyTable();
+        visitor.append(thisObject->m_propertyTableUnsafe);
+    else if (thisObject->m_propertyTableUnsafe)
+        thisObject->m_propertyTableUnsafe.clear();
 }
 
 bool Structure::isCheapDuringGC(VM& vm)
@@ -1306,7 +1306,7 @@ bool Structure::canCachePropertyNameEnumerator(VM& vm) const
     if (!this->canCacheOwnKeys())
         return false;
 
-    StructureChain* structureChain = cachedPrototypeChain();
+    StructureChain* structureChain = m_cachedPrototypeChain.get();
     ASSERT(structureChain);
     StructureID* currentStructureID = structureChain->head();
     while (true) {
index d02879f..76759b6 100644 (file)
@@ -43,7 +43,6 @@
 #include "TinyBloomFilter.h"
 #include "Watchpoint.h"
 #include "WriteBarrierInlines.h"
-#include <wtf/CompactRefPtrTuple.h>
 #include <wtf/PrintStream.h>
 
 namespace WTF {
@@ -261,18 +260,9 @@ public:
     {
         return typeInfo().getOwnPropertySlotIsImpure();
     }
-
-    TypeInfo::OutOfLineTypeFlags outOfLineTypeFlags() const
-    {
-#if CPU(ADDRESS64)
-        return m_outOfLineTypeFlagsAndPropertyTableUnsafe.type();
-#else
-        return m_outOfLineTypeFlags;
-#endif
-    }
     
     // Type accessors.
-    TypeInfo typeInfo() const { return m_blob.typeInfo(outOfLineTypeFlags()); }
+    TypeInfo typeInfo() const { return m_blob.typeInfo(m_outOfLineTypeFlags); }
     bool isObject() const { return typeInfo().isObject(); }
 
     IndexingType indexingType() const { return m_blob.indexingModeIncludingHistory() & AllWritableArrayTypes; }
@@ -327,24 +317,24 @@ public:
     
     bool hasRareData() const
     {
-        return isRareData(cachedPrototypeChainOrRareData());
+        return isRareData(m_previousOrRareData.get());
     }
 
     StructureRareData* rareData()
     {
         ASSERT(hasRareData());
-        return static_cast<StructureRareData*>(cachedPrototypeChainOrRareData());
+        return static_cast<StructureRareData*>(m_previousOrRareData.get());
     }
 
     const StructureRareData* rareData() const
     {
         ASSERT(hasRareData());
-        return static_cast<const StructureRareData*>(cachedPrototypeChainOrRareData());
+        return static_cast<const StructureRareData*>(m_previousOrRareData.get());
     }
 
     const StructureRareData* rareDataConcurrently() const
     {
-        JSCell* cell = cachedPrototypeChainOrRareData();
+        JSCell* cell = m_previousOrRareData.get();
         if (isRareData(cell))
             return static_cast<StructureRareData*>(cell);
         return nullptr;
@@ -357,21 +347,21 @@ public:
         return rareData();
     }
     
-    Structure* previousID(VM& vm) const
+    Structure* previousID() const
     {
-        if (!m_previousID)
-            return nullptr;
-        return vm.getStructure(m_previousID);
+        ASSERT(structure()->classInfo() == info());
+        // This is so written because it's used concurrently. We only load from m_previousOrRareData
+        // once, and this load is guaranteed atomic.
+        JSCell* cell = m_previousOrRareData.get();
+        if (isRareData(cell))
+            return static_cast<StructureRareData*>(cell)->previousID();
+        return static_cast<Structure*>(cell);
     }
     bool transitivelyTransitionedFrom(Structure* structureToFind);
 
     PropertyOffset maxOffset() const
     {
-#if CPU(ADDRESS64)
-        uint16_t maxOffset = m_maxOffsetAndTransitionPropertyName.type();
-#else
         uint16_t maxOffset = m_maxOffset;
-#endif
         if (maxOffset == shortInvalidOffset)
             return invalidOffset;
         if (maxOffset == useRareDataFlag)
@@ -381,45 +371,22 @@ public:
 
     void setMaxOffset(VM& vm, PropertyOffset offset)
     {
-        ASSERT(!isCompilationThread() && !Thread::mayBeGCThread());
-        auto commit = [&](uint16_t value) {
-#if CPU(ADDRESS64)
-            m_maxOffsetAndTransitionPropertyName.setType(value);
-#else
-            m_maxOffset = value;
-#endif
-        };
-
-        if (offset == invalidOffset) {
-            commit(shortInvalidOffset);
-            return;
-        }
-        if (offset < useRareDataFlag && offset < shortInvalidOffset) {
-            commit(offset);
-            return;
-        }
-#if CPU(ADDRESS64)
-        uint16_t maxOffset = m_maxOffsetAndTransitionPropertyName.type();
-#else
-        uint16_t maxOffset = m_maxOffset;
-#endif
-        if (maxOffset == useRareDataFlag) {
+        if (offset == invalidOffset)
+            m_maxOffset = shortInvalidOffset;
+        else if (offset < useRareDataFlag && offset < shortInvalidOffset)
+            m_maxOffset = offset;
+        else if (m_maxOffset == useRareDataFlag)
             rareData()->m_maxOffset = offset;
-            return;
+        else {
+            ensureRareData(vm)->m_maxOffset = offset;
+            WTF::storeStoreFence();
+            m_maxOffset = useRareDataFlag;
         }
-
-        ensureRareData(vm)->m_maxOffset = offset;
-        WTF::storeStoreFence();
-        commit(useRareDataFlag);
     }
 
     PropertyOffset transitionOffset() const
     {
-#if CPU(ADDRESS64)
-        uint16_t transitionOffset = m_transitionOffsetAndClassInfo.type();
-#else
         uint16_t transitionOffset = m_transitionOffset;
-#endif
         if (transitionOffset == shortInvalidOffset)
             return invalidOffset;
         if (transitionOffset == useRareDataFlag)
@@ -429,36 +396,17 @@ public:
 
     void setTransitionOffset(VM& vm, PropertyOffset offset)
     {
-        ASSERT(!isCompilationThread() && !Thread::mayBeGCThread());
-        auto commit = [&](uint16_t value) {
-#if CPU(ADDRESS64)
-            m_transitionOffsetAndClassInfo.setType(value);
-#else
-            m_transitionOffset = value;
-#endif
-        };
-
-        if (offset == invalidOffset) {
-            commit(shortInvalidOffset);
-            return;
-        }
-        if (offset < useRareDataFlag && offset < shortInvalidOffset) {
-            commit(offset);
-            return;
-        }
-#if CPU(ADDRESS64)
-        uint16_t transitionOffset = m_transitionOffsetAndClassInfo.type();
-#else
-        uint16_t transitionOffset = m_transitionOffset;
-#endif
-        if (transitionOffset == useRareDataFlag) {
+        if (offset == invalidOffset)
+            m_transitionOffset = shortInvalidOffset;
+        else if (offset < useRareDataFlag && offset < shortInvalidOffset)
+            m_transitionOffset = offset;
+        else if (m_transitionOffset == useRareDataFlag)
             rareData()->m_transitionOffset = offset;
-            return;
+        else {
+            ensureRareData(vm)->m_transitionOffset = offset;
+            WTF::storeStoreFence();
+            m_transitionOffset = useRareDataFlag;
         }
-
-        ensureRareData(vm)->m_transitionOffset = offset;
-        WTF::storeStoreFence();
-        commit(useRareDataFlag);
     }
 
     static unsigned outOfLineCapacity(PropertyOffset maxOffset)
@@ -494,18 +442,17 @@ public:
     {
         return outOfLineSize(maxOffset());
     }
-    bool hasInlineStorage() const { return !!inlineCapacity(); }
+    bool hasInlineStorage() const
+    {
+        return !!m_inlineCapacity;
+    }
     unsigned inlineCapacity() const
     {
-#if CPU(ADDRESS64)
-        return static_cast<uint8_t>(m_inlineCapacityAndCachedPrototypeChainOrRareData.type());
-#else
         return m_inlineCapacity;
-#endif
     }
     unsigned inlineSize() const
     {
-        return std::min<unsigned>(maxOffset() + 1, inlineCapacity());
+        return std::min<unsigned>(maxOffset() + 1, m_inlineCapacity);
     }
     unsigned totalStorageCapacity() const
     {
@@ -517,12 +464,12 @@ public:
     {
         return JSC::isValidOffset(offset)
             && offset <= maxOffset()
-            && (offset < static_cast<int>(inlineCapacity()) || offset >= firstOutOfLineOffset);
+            && (offset < m_inlineCapacity || offset >= firstOutOfLineOffset);
     }
 
     bool hijacksIndexingHeader() const
     {
-        return isTypedView(classInfo()->typedArrayStorageType);
+        return isTypedView(m_classInfo->typedArrayStorageType);
     }
     
     bool couldHaveIndexingHeader() const
@@ -592,14 +539,7 @@ public:
 
     void setObjectToStringValue(JSGlobalObject*, VM&, JSString* value, PropertySlot toStringTagSymbolSlot);
 
-    const ClassInfo* classInfo() const
-    {
-#if CPU(ADDRESS64)
-        return m_transitionOffsetAndClassInfo.pointer();
-#else
-        return m_classInfo;
-#endif
-    }
+    const ClassInfo* classInfo() const { return m_classInfo; }
 
     static ptrdiff_t structureIDOffset()
     {
@@ -616,39 +556,29 @@ public:
         return OBJECT_OFFSETOF(Structure, m_globalObject);
     }
 
-    static ptrdiff_t offsetOfClassInfo()
+    static ptrdiff_t classInfoOffset()
     {
-#if CPU(ADDRESS64)
-        return OBJECT_OFFSETOF(Structure, m_transitionOffsetAndClassInfo);
-#else
         return OBJECT_OFFSETOF(Structure, m_classInfo);
-#endif
     }
-
+        
     static ptrdiff_t indexingModeIncludingHistoryOffset()
     {
         return OBJECT_OFFSETOF(Structure, m_blob) + StructureIDBlob::indexingModeIncludingHistoryOffset();
     }
+    
+    static ptrdiff_t propertyTableUnsafeOffset()
+    {
+        return OBJECT_OFFSETOF(Structure, m_propertyTableUnsafe);
+    }
 
-#if CPU(LITTLE_ENDIAN)
-    static ptrdiff_t offsetOfInlineCapacity()
+    static ptrdiff_t inlineCapacityOffset()
     {
-#if CPU(ADDRESS64)
-        return OBJECT_OFFSETOF(Structure, m_inlineCapacityAndCachedPrototypeChainOrRareData) + CompactPointerTuple<JSCell*, uint16_t>::offsetOfType();
-#else
         return OBJECT_OFFSETOF(Structure, m_inlineCapacity);
-#endif
-
     }
-#endif
 
-    static ptrdiff_t offsetOfCachedPrototypeChainOrRareData()
+    static ptrdiff_t previousOrRareDataOffset()
     {
-#if CPU(ADDRESS64)
-        return OBJECT_OFFSETOF(Structure, m_inlineCapacityAndCachedPrototypeChainOrRareData);
-#else
-        return OBJECT_OFFSETOF(Structure, m_cachedPrototypeChainOrRareData);
-#endif
+        return OBJECT_OFFSETOF(Structure, m_previousOrRareData);
     }
 
     static Structure* createStructure(VM&);
@@ -727,16 +657,11 @@ public:
     
     static void dumpContextHeader(PrintStream&);
     
-    static bool shouldConvertToPolyProto(const Structure* a, const Structure* b);
+    ConcurrentJSLock& lock() { return m_lock; }
 
-    UniquedStringImpl* transitionPropertyName() const
-    {
-#if CPU(ADDRESS64)
-        return m_maxOffsetAndTransitionPropertyName.pointer();
-#else
-        return m_transitionPropertyName.get();
-#endif
-    }
+    unsigned propertyHash() const { return m_propertyHash; }
+
+    static bool shouldConvertToPolyProto(const Structure* a, const Structure* b);
 
     struct PropertyHashEntry {
         const HashTable* table;
@@ -747,25 +672,6 @@ public:
     DECLARE_EXPORT_INFO;
 
 private:
-    bool ruleOutUnseenProperty(UniquedStringImpl*) const;
-#if CPU(ADDRESS64)
-    // As a propertyHash, 64bit environment uses 16bit property-hash + seenProperties set.
-    uintptr_t propertyHash() const { return m_propertyHashAndSeenProperties.data(); }
-#else
-    uint32_t propertyHash() const { return m_propertyHash; }
-#endif
-    TinyBloomFilter seenProperties() const;
-    void addPropertyHashAndSeenProperty(unsigned, UniquedStringImpl*);
-
-    void setTransitionPropertyName(const AbstractLocker&, UniquedStringImpl* transitionPropertyName)
-    {
-#if CPU(ADDRESS64)
-        m_maxOffsetAndTransitionPropertyName.setPointer(transitionPropertyName);
-#else
-        m_transitionPropertyName = transitionPropertyName;
-#endif
-    }
-
     typedef enum { 
         NoneDictionaryKind = 0,
         CachedDictionaryKind = 1,
@@ -782,7 +688,6 @@ public:
     {\
         m_bitField &= ~(s_##lowerName##Mask << offset);\
         m_bitField |= (newValue & s_##lowerName##Mask) << offset;\
-        ASSERT(newValue == lowerName());\
     }
 
     DEFINE_BITFIELD(DictionaryKind, dictionaryKind, DictionaryKind, 2, 0);
@@ -790,18 +695,18 @@ public:
     DEFINE_BITFIELD(bool, hasGetterSetterProperties, HasGetterSetterProperties, 1, 3);
     DEFINE_BITFIELD(bool, hasReadOnlyOrGetterSetterPropertiesExcludingProto, HasReadOnlyOrGetterSetterPropertiesExcludingProto, 1, 4);
     DEFINE_BITFIELD(bool, isQuickPropertyAccessAllowedForEnumeration, IsQuickPropertyAccessAllowedForEnumeration, 1, 5);
-    DEFINE_BITFIELD(unsigned, transitionPropertyAttributes, TransitionPropertyAttributes, 8, 6);
-    DEFINE_BITFIELD(bool, didPreventExtensions, DidPreventExtensions, 1, 14);
-    DEFINE_BITFIELD(bool, didTransition, DidTransition, 1, 15);
-    DEFINE_BITFIELD(bool, staticPropertiesReified, StaticPropertiesReified, 1, 16);
-    DEFINE_BITFIELD(bool, hasBeenFlattenedBefore, HasBeenFlattenedBefore, 1, 17);
-    DEFINE_BITFIELD(bool, hasCustomGetterSetterProperties, HasCustomGetterSetterProperties, 1, 18);
-    DEFINE_BITFIELD(bool, didWatchInternalProperties, DidWatchInternalProperties, 1, 19);
-    DEFINE_BITFIELD(bool, transitionWatchpointIsLikelyToBeFired, TransitionWatchpointIsLikelyToBeFired, 1, 20);
-    DEFINE_BITFIELD(bool, hasBeenDictionary, HasBeenDictionary, 1, 21);
-    DEFINE_BITFIELD(bool, protectPropertyTableWhileTransitioning, ProtectPropertyTableWhileTransitioning, 1, 22);
-    DEFINE_BITFIELD(bool, hasUnderscoreProtoPropertyExcludingOriginalProto, HasUnderscoreProtoPropertyExcludingOriginalProto, 1, 23);
-    DEFINE_BITFIELD(bool, isPropertyDeletionTransition, IsPropertyDeletionTransition, 1, 24);
+    DEFINE_BITFIELD(unsigned, transitionPropertyAttributes, TransitionPropertyAttributes, 14, 6);
+    DEFINE_BITFIELD(bool, didPreventExtensions, DidPreventExtensions, 1, 20);
+    DEFINE_BITFIELD(bool, didTransition, DidTransition, 1, 21);
+    DEFINE_BITFIELD(bool, staticPropertiesReified, StaticPropertiesReified, 1, 22);
+    DEFINE_BITFIELD(bool, hasBeenFlattenedBefore, HasBeenFlattenedBefore, 1, 23);
+    DEFINE_BITFIELD(bool, hasCustomGetterSetterProperties, HasCustomGetterSetterProperties, 1, 24);
+    DEFINE_BITFIELD(bool, didWatchInternalProperties, DidWatchInternalProperties, 1, 25);
+    DEFINE_BITFIELD(bool, transitionWatchpointIsLikelyToBeFired, TransitionWatchpointIsLikelyToBeFired, 1, 26);
+    DEFINE_BITFIELD(bool, hasBeenDictionary, HasBeenDictionary, 1, 27);
+    DEFINE_BITFIELD(bool, protectPropertyTableWhileTransitioning, ProtectPropertyTableWhileTransitioning, 1, 28);
+    DEFINE_BITFIELD(bool, hasUnderscoreProtoPropertyExcludingOriginalProto, HasUnderscoreProtoPropertyExcludingOriginalProto, 1, 29);
+    DEFINE_BITFIELD(bool, isPropertyDeletionTransition, IsPropertyDeletionTransition, 1, 30);
 
     static_assert(s_bitWidthOfTransitionPropertyAttributes <= sizeof(TransitionPropertyAttributes) * 8);
 
@@ -821,7 +726,7 @@ private:
     // and the list of structures that we visited before we got to it. If it returns a
     // non-null structure, it will also lock the structure that it returns; it is your job
     // to unlock it.
-    void findStructuresAndMapForMaterialization(VM&, Vector<Structure*, 8>& structures, Structure*&, PropertyTable*&);
+    void findStructuresAndMapForMaterialization(Vector<Structure*, 8>& structures, Structure*&, PropertyTable*&);
     
     static Structure* toDictionaryTransition(VM&, Structure*, DictionaryKind, DeferredStructureTransitionWatchpointFire* = nullptr);
 
@@ -838,9 +743,9 @@ private:
     // This may grab the lock, or not. Do not call when holding the Structure's lock.
     PropertyTable* ensurePropertyTableIfNotEmpty(VM& vm)
     {
-        if (PropertyTable* result = propertyTableUnsafeOrNull())
+        if (PropertyTable* result = m_propertyTableUnsafe.get())
             return result;
-        if (!previousID(vm))
+        if (!previousID())
             return nullptr;
         return materializePropertyTable(vm);
     }
@@ -848,37 +753,39 @@ private:
     // This may grab the lock, or not. Do not call when holding the Structure's lock.
     PropertyTable* ensurePropertyTable(VM& vm)
     {
-        if (PropertyTable* result = propertyTableUnsafeOrNull())
+        if (PropertyTable* result = m_propertyTableUnsafe.get())
             return result;
         return materializePropertyTable(vm);
     }
     
-    PropertyTable* propertyTableUnsafeOrNull() const
+    PropertyTable* propertyTableOrNull() const
     {
-#if CPU(ADDRESS64)
-        return m_outOfLineTypeFlagsAndPropertyTableUnsafe.pointer();
-#else
         return m_propertyTableUnsafe.get();
-#endif
     }
     
     // This will grab the lock. Do not call when holding the Structure's lock.
     JS_EXPORT_PRIVATE PropertyTable* materializePropertyTable(VM&, bool setPropertyTable = true);
     
     void setPropertyTable(VM& vm, PropertyTable* table);
-    void clearPropertyTable();
     
     PropertyTable* takePropertyTableOrCloneIfPinned(VM&);
     PropertyTable* copyPropertyTableForPinning(VM&);
 
     void setPreviousID(VM&, Structure*);
-    void clearPreviousID();
+
+    void clearPreviousID()
+    {
+        if (hasRareData())
+            rareData()->clearPreviousID();
+        else
+            m_previousOrRareData.clear();
+    }
 
     int transitionCountEstimate() const
     {
         // Since the number of transitions is often the same as the last offset (except if there are deletes)
         // we keep the size of Structure down by not storing both.
-        return numberOfSlotsForMaxOffset(maxOffset(), inlineCapacity());
+        return numberOfSlotsForMaxOffset(maxOffset(), m_inlineCapacity);
     }
 
     bool isValid(JSGlobalObject*, StructureChain* cachedPrototypeChain, JSObject* base) const;
@@ -889,7 +796,7 @@ private:
     
     bool isRareData(JSCell* cell) const
     {
-        return cell && cell->type() == StructureRareDataType;
+        return cell && cell->structureID() != structureID();
     }
 
     template<typename DetailsFunc>
@@ -900,79 +807,48 @@ private:
     
     void startWatchingInternalProperties(VM&);
 
-    StructureChain* cachedPrototypeChain() const;
-    void setCachedPrototypeChain(VM&, StructureChain*);
-
-    void setOutOfLineTypeFlags(TypeInfo::OutOfLineTypeFlags);
-    void setClassInfo(const ClassInfo*);
-    void setInlineCapacity(uint8_t);
-
-    JSCell* cachedPrototypeChainOrRareData() const
-    {
-#if CPU(ADDRESS64)
-        return m_inlineCapacityAndCachedPrototypeChainOrRareData.pointer();
-#else
-        return m_cachedPrototypeChainOrRareData.get();
-#endif
-    }
-
     static constexpr int s_maxTransitionLength = 64;
     static constexpr int s_maxTransitionLengthForNonEvalPutById = 512;
 
     // These need to be properly aligned at the beginning of the 'Structure'
     // part of the object.
     StructureIDBlob m_blob;
+    TypeInfo::OutOfLineTypeFlags m_outOfLineTypeFlags;
 
-    // The property table pointer should be accessed through ensurePropertyTable(). During GC, m_propertyTableUnsafe field part may be set to 0 by another thread.
-    // During a Heap Snapshot GC we avoid clearing the table so it is safe to use.
-#if CPU(ADDRESS64)
-public:
-    static constexpr uintptr_t classInfoMask = CompactPointerTuple<const ClassInfo*, uint16_t>::pointerMask;
-    static constexpr uintptr_t cachedPrototypeChainOrRareDataMask = CompactPointerTuple<JSCell*, uint16_t>::pointerMask;
-private:
-    // Structure is one of the most frequently allocated data structure. Moreover, Structure tends to be alive a long time!
-    // This motivates extra complicated hack which optimizes sizeof(Structure).
-    //
-    // We combine 16bit data and 64bit pointer into one pointer-size field to (1) save memory while (2) not losing atomic load/store.
-    // The key here is analyzing data access patterns carefully. They are categoriezed into three types.
-    //     1. ImmutableAfterConstruction
-    //     2. MutableFromAnyThread
-    //     3. MutableFromMainThread
-    //  We assume that loading happens from any threads. Under this assumption, MutableFromAnyThread + (MutableFromMainThread / MutableFromAnyThread) is the pair which is racy.
-    //  Other pairs works well. We carefully put assertions to setters, analyze access patterns and pick appropriate pairs in Structure fields.
-    CompactPointerTuple<PropertyTable*, TypeInfo::OutOfLineTypeFlags> m_outOfLineTypeFlagsAndPropertyTableUnsafe; // ImmutableAfterConstruction(m_outOfLineTypeFlags) and MutableFromAnyThread(m_propertyTableUnsafe).
-    CompactRefPtrTuple<UniquedStringImpl, uint16_t> m_maxOffsetAndTransitionPropertyName; // MutableFromMainThread(m_maxOffset) and MutableFromMainThread(m_transitionPropertyName).
-    CompactPointerTuple<const ClassInfo*, uint16_t> m_transitionOffsetAndClassInfo; // MutableFromMainThread(m_transitionOffset) and ImmutableAfterConstruction(m_classInfo).
-    CompactPointerTuple<JSCell*, uint16_t> m_inlineCapacityAndCachedPrototypeChainOrRareData; // ImmutableAfterConstruction(m_inlineCapacity) and MutableFromMainThread(m_cachedPrototypeChainOrRareData).
-    CompactPointerTuple<UniquedStringImpl*, uint16_t> m_propertyHashAndSeenProperties; // MutableFromMainThread(m_propertyHash) and MutableFromMainThread(m_seenProperties).
-#else
-    TypeInfo::OutOfLineTypeFlags m_outOfLineTypeFlags { 0 };
-    uint8_t m_inlineCapacity { 0 };
-    uint32_t m_propertyHash { 0 };
-    uint16_t m_transitionOffset { 0 };
-    uint16_t m_maxOffset { 0 };
-    WriteBarrier<PropertyTable> m_propertyTableUnsafe;
-    const ClassInfo* m_classInfo { nullptr };
-    WriteBarrier<JSCell> m_cachedPrototypeChainOrRareData;
-    uintptr_t m_seenProperties { 0 };
-    RefPtr<UniquedStringImpl> m_transitionPropertyName;
-#endif
-    StructureID m_previousID { 0 };
-    uint32_t m_bitField { 0 };
+    uint8_t m_inlineCapacity;
+
+    ConcurrentJSLock m_lock;
+
+    uint32_t m_bitField;
 
-    StructureTransitionTable m_transitionTable;
     WriteBarrier<JSGlobalObject> m_globalObject;
     WriteBarrier<Unknown> m_prototype;
+    mutable WriteBarrier<StructureChain> m_cachedPrototypeChain;
+
+    WriteBarrier<JSCell> m_previousOrRareData;
+
+    RefPtr<UniquedStringImpl> m_transitionPropertyName;
+
+    const ClassInfo* m_classInfo;
+
+    StructureTransitionTable m_transitionTable;
+
+    // Should be accessed through ensurePropertyTable(). During GC, it may be set to 0 by another thread.
+    // During a Heap Snapshot GC we avoid clearing the table so it is safe to use.
+    WriteBarrier<PropertyTable> m_propertyTableUnsafe;
 
     mutable InlineWatchpointSet m_transitionWatchpointSet;
 
     COMPILE_ASSERT(firstOutOfLineOffset < 256, firstOutOfLineOffset_fits);
 
+    uint16_t m_transitionOffset;
+    uint16_t m_maxOffset;
+
+    uint32_t m_propertyHash;
+    TinyBloomFilter m_seenProperties;
+
     friend class VMInspector;
     friend class JSDollarVMHelper;
 };
-#if CPU(ADDRESS64)
-static_assert(sizeof(Structure) <= 96, "Do not increase sizeof(Structure), it immediately causes memory regression");
-#endif
 
 } // namespace JSC
index 24b2a69..b2ed858 100644 (file)
@@ -144,7 +144,7 @@ ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, u
     ASSERT(!isCompilationThread());
     ASSERT(structure(vm)->classInfo() == info());
 
-    if (ruleOutUnseenProperty(propertyName.uid()))
+    if (m_seenProperties.ruleOut(bitwise_cast<uintptr_t>(propertyName.uid())))
         return invalidOffset;
 
     PropertyTable* propertyTable = ensurePropertyTableIfNotEmpty(vm);
@@ -159,57 +159,29 @@ ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, u
     return entry->offset;
 }
 
-inline bool Structure::ruleOutUnseenProperty(UniquedStringImpl* uid) const
-{
-    ASSERT(uid);
-    return seenProperties().ruleOut(bitwise_cast<uintptr_t>(uid));
-}
-
-inline TinyBloomFilter Structure::seenProperties() const
-{
-#if CPU(ADDRESS64)
-    return TinyBloomFilter(bitwise_cast<uintptr_t>(m_propertyHashAndSeenProperties.pointer()));
-#else
-    return TinyBloomFilter(m_seenProperties);
-#endif
-}
-
-inline void Structure::addPropertyHashAndSeenProperty(unsigned hash, UniquedStringImpl* pointer)
-{
-#if CPU(ADDRESS64)
-    m_propertyHashAndSeenProperties.setType(m_propertyHashAndSeenProperties.type() ^ hash);
-    m_propertyHashAndSeenProperties.setPointer(bitwise_cast<UniquedStringImpl*>(bitwise_cast<uintptr_t>(m_propertyHashAndSeenProperties.pointer()) | bitwise_cast<uintptr_t>(pointer)));
-#else
-    m_propertyHash = m_propertyHash ^ hash;
-    m_seenProperties = bitwise_cast<uintptr_t>(pointer) | m_seenProperties;
-#endif
-}
-
 template<typename Functor>
 void Structure::forEachPropertyConcurrently(const Functor& functor)
 {
     Vector<Structure*, 8> structures;
     Structure* tableStructure;
     PropertyTable* table;
-    VM& vm = this->vm();
     
-    findStructuresAndMapForMaterialization(vm, structures, tableStructure, table);
+    findStructuresAndMapForMaterialization(structures, tableStructure, table);
 
     HashSet<UniquedStringImpl*> seenProperties;
 
-    for (Structure* structure : structures) {
-        UniquedStringImpl* transitionPropertyName = structure->transitionPropertyName();
-        if (!transitionPropertyName || seenProperties.contains(transitionPropertyName))
+    for (auto* structure : structures) {
+        if (!structure->m_transitionPropertyName || seenProperties.contains(structure->m_transitionPropertyName.get()))
             continue;
 
-        seenProperties.add(transitionPropertyName);
+        seenProperties.add(structure->m_transitionPropertyName.get());
 
         if (structure->isPropertyDeletionTransition())
             continue;
 
-        if (!functor(PropertyMapEntry(transitionPropertyName, structure->transitionOffset(), structure->transitionPropertyAttributes()))) {
+        if (!functor(PropertyMapEntry(structure->m_transitionPropertyName.get(), structure->transitionOffset(), structure->transitionPropertyAttributes()))) {
             if (table)
-                tableStructure->cellLock().unlock();
+                tableStructure->m_lock.unlock();
             return;
         }
     }
@@ -220,11 +192,11 @@ void Structure::forEachPropertyConcurrently(const Functor& functor)
                 continue;
 
             if (!functor(entry)) {
-                tableStructure->cellLock().unlock();
+                tableStructure->m_lock.unlock();
                 return;
             }
         }
-        tableStructure->cellLock().unlock();
+        tableStructure->m_lock.unlock();
     }
 }
 
@@ -279,8 +251,7 @@ inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObjec
 
 inline bool Structure::transitivelyTransitionedFrom(Structure* structureToFind)
 {
-    VM& vm = this->vm();
-    for (Structure* current = this; current; current = current->previousID(vm)) {
+    for (Structure* current = this; current; current = current->previousID()) {
         if (current == structureToFind)
             return true;
     }
@@ -347,41 +318,15 @@ inline JSValue Structure::prototypeForLookup(JSGlobalObject* globalObject, JSCel
     return prototypeForLookupPrimitiveImpl(globalObject, this);
 }
 
-inline StructureChain* Structure::cachedPrototypeChain() const
-{
-    JSCell* cell = cachedPrototypeChainOrRareData();
-    if (isRareData(cell))
-        return jsCast<StructureRareData*>(cell)->cachedPrototypeChain();
-    return jsCast<StructureChain*>(cell);
-}
-
-inline void Structure::setCachedPrototypeChain(VM& vm, StructureChain* chain)
-{
-    ASSERT(isObject());
-    ASSERT(!isCompilationThread() && !Thread::mayBeGCThread());
-    JSCell* cell = cachedPrototypeChainOrRareData();
-    if (isRareData(cell)) {
-        jsCast<StructureRareData*>(cell)->setCachedPrototypeChain(vm, chain);
-        return;
-    }
-#if CPU(ADDRESS64)
-    m_inlineCapacityAndCachedPrototypeChainOrRareData.setPointer(chain);
-    vm.heap.writeBarrier(this, chain);
-#else
-    m_cachedPrototypeChainOrRareData.setMayBeNull(vm, this, chain);
-#endif
-}
-
 inline StructureChain* Structure::prototypeChain(VM& vm, JSGlobalObject* globalObject, JSObject* base) const
 {
-    ASSERT(this->isObject());
     ASSERT(base->structure(vm) == this);
     // We cache our prototype chain so our clients can share it.
-    if (!isValid(globalObject, cachedPrototypeChain(), base)) {
+    if (!isValid(globalObject, m_cachedPrototypeChain.get(), base)) {
         JSValue prototype = prototypeForLookup(globalObject, base);
-        const_cast<Structure*>(this)->setCachedPrototypeChain(vm, StructureChain::create(vm, prototype.isNull() ? nullptr : asObject(prototype)));
+        m_cachedPrototypeChain.set(vm, this, StructureChain::create(vm, prototype.isNull() ? nullptr : asObject(prototype)));
     }
-    return cachedPrototypeChain();
+    return m_cachedPrototypeChain.get();
 }
 
 inline StructureChain* Structure::prototypeChain(JSGlobalObject* globalObject, JSObject* base) const
@@ -421,7 +366,7 @@ inline void Structure::didReplaceProperty(PropertyOffset offset)
 
 inline WatchpointSet* Structure::propertyReplacementWatchpointSet(PropertyOffset offset)
 {
-    ConcurrentJSCellLocker locker(cellLock());
+    ConcurrentJSLocker locker(m_lock);
     if (!hasRareData())
         return nullptr;
     WTF::loadLoadFence();
@@ -442,16 +387,16 @@ ALWAYS_INLINE bool Structure::checkOffsetConsistency(PropertyTable* propertyTabl
         return true;
     
     unsigned totalSize = propertyTable->propertyStorageSize();
-    unsigned inlineOverflowAccordingToTotalSize = totalSize < inlineCapacity() ? 0 : totalSize - inlineCapacity();
+    unsigned inlineOverflowAccordingToTotalSize = totalSize < m_inlineCapacity ? 0 : totalSize - m_inlineCapacity;
 
     auto fail = [&] (const char* description) {
         dataLog("Detected offset inconsistency: ", description, "!\n");
         dataLog("this = ", RawPointer(this), "\n");
         dataLog("transitionOffset = ", transitionOffset(), "\n");
         dataLog("maxOffset = ", maxOffset(), "\n");
-        dataLog("m_inlineCapacity = ", inlineCapacity(), "\n");
+        dataLog("m_inlineCapacity = ", m_inlineCapacity, "\n");
         dataLog("propertyTable = ", RawPointer(propertyTable), "\n");
-        dataLog("numberOfSlotsForMaxOffset = ", numberOfSlotsForMaxOffset(maxOffset(), inlineCapacity()), "\n");
+        dataLog("numberOfSlotsForMaxOffset = ", numberOfSlotsForMaxOffset(maxOffset(), m_inlineCapacity), "\n");
         dataLog("totalSize = ", totalSize, "\n");
         dataLog("inlineOverflowAccordingToTotalSize = ", inlineOverflowAccordingToTotalSize, "\n");
         dataLog("numberOfOutOfLineSlotsForMaxOffset = ", numberOfOutOfLineSlotsForMaxOffset(maxOffset()), "\n");
@@ -459,7 +404,7 @@ ALWAYS_INLINE bool Structure::checkOffsetConsistency(PropertyTable* propertyTabl
         UNREACHABLE_FOR_PLATFORM();
     };
     
-    if (numberOfSlotsForMaxOffset(maxOffset(), inlineCapacity()) != totalSize)
+    if (numberOfSlotsForMaxOffset(maxOffset(), m_inlineCapacity) != totalSize)
         fail("numberOfSlotsForMaxOffset doesn't match totalSize");
     if (inlineOverflowAccordingToTotalSize != numberOfOutOfLineSlotsForMaxOffset(maxOffset()))
         fail("inlineOverflowAccordingToTotalSize doesn't match numberOfOutOfLineSlotsForMaxOffset");
@@ -469,7 +414,7 @@ ALWAYS_INLINE bool Structure::checkOffsetConsistency(PropertyTable* propertyTabl
 
 ALWAYS_INLINE bool Structure::checkOffsetConsistency() const
 {
-    PropertyTable* propertyTable = propertyTableUnsafeOrNull();
+    PropertyTable* propertyTable = propertyTableOrNull();
 
     if (!propertyTable) {
         ASSERT(!isPinnedPropertyTable());
@@ -510,7 +455,7 @@ inline PropertyOffset Structure::add(VM& vm, PropertyName propertyName, unsigned
 {
     PropertyTable* table = ensurePropertyTable(vm);
 
-    GCSafeConcurrentJSCellLocker locker(cellLock(), vm.heap);
+    GCSafeConcurrentJSLocker locker(m_lock, vm.heap);
 
     switch (shouldPin) {
     case ShouldPin::Yes:
@@ -531,9 +476,10 @@ inline PropertyOffset Structure::add(VM& vm, PropertyName propertyName, unsigned
 
     auto rep = propertyName.uid();
 
-    PropertyOffset newOffset = table->nextOffset(inlineCapacity());
+    PropertyOffset newOffset = table->nextOffset(m_inlineCapacity);
 
-    addPropertyHashAndSeenProperty(rep->existingSymbolAwareHash(), rep);
+    m_propertyHash = m_propertyHash ^ rep->existingSymbolAwareHash();
+    m_seenProperties.add(bitwise_cast<uintptr_t>(rep));
 
     auto result = table->add(PropertyMapEntry(rep, newOffset, attributes));
     ASSERT_UNUSED(result, result.second);
@@ -552,7 +498,7 @@ template<Structure::ShouldPin shouldPin, typename Func>
 inline PropertyOffset Structure::remove(VM& vm, PropertyName propertyName, const Func& func)
 {
     PropertyTable* table = ensurePropertyTable(vm);
-    GCSafeConcurrentJSCellLocker locker(cellLock(), vm.heap);
+    GCSafeConcurrentJSLocker locker(m_lock, vm.heap);
 
     switch (shouldPin) {
     case ShouldPin::Yes:
@@ -602,7 +548,7 @@ inline PropertyOffset Structure::removePropertyWithoutTransition(VM& vm, Propert
 {
     ASSERT(isUncacheableDictionary());
     ASSERT(isPinnedPropertyTable());
-    ASSERT(propertyTableUnsafeOrNull());
+    ASSERT(propertyTableOrNull());
     
     return remove<ShouldPin::Yes>(vm, propertyName, func);
 }
@@ -620,60 +566,15 @@ ALWAYS_INLINE void Structure::setGlobalObject(VM& vm, JSGlobalObject* globalObje
 
 ALWAYS_INLINE void Structure::setPropertyTable(VM& vm, PropertyTable* table)
 {
-#if CPU(ADDRESS64)
-    m_outOfLineTypeFlagsAndPropertyTableUnsafe.setPointer(table);
-    vm.heap.writeBarrier(this, table);
-#else
     m_propertyTableUnsafe.setMayBeNull(vm, this, table);
-#endif
-}
-
-ALWAYS_INLINE void Structure::clearPropertyTable()
-{
-#if CPU(ADDRESS64)
-    m_outOfLineTypeFlagsAndPropertyTableUnsafe.setPointer(nullptr);
-#else
-    m_propertyTableUnsafe.clear();
-#endif
-}
-
-ALWAYS_INLINE void Structure::setOutOfLineTypeFlags(TypeInfo::OutOfLineTypeFlags outOfLineTypeFlags)
-{
-#if CPU(ADDRESS64)
-    m_outOfLineTypeFlagsAndPropertyTableUnsafe.setType(outOfLineTypeFlags);
-#else
-    m_outOfLineTypeFlags = outOfLineTypeFlags;
-#endif
-}
-
-ALWAYS_INLINE void Structure::setInlineCapacity(uint8_t inlineCapacity)
-{
-#if CPU(ADDRESS64)
-    m_inlineCapacityAndCachedPrototypeChainOrRareData.setType(inlineCapacity);
-#else
-    m_inlineCapacity = inlineCapacity;
-#endif
-}
-
-ALWAYS_INLINE void Structure::setClassInfo(const ClassInfo* classInfo)
-{
-#if CPU(ADDRESS64)
-    m_transitionOffsetAndClassInfo.setPointer(classInfo);
-#else
-    m_classInfo = classInfo;
-#endif
 }
 
 ALWAYS_INLINE void Structure::setPreviousID(VM& vm, Structure* structure)
 {
-    ASSERT(structure);
-    m_previousID = structure->id();
-    vm.heap.writeBarrier(this, structure);
-}
-
-inline void Structure::clearPreviousID()
-{
-    m_previousID = 0;
+    if (hasRareData())
+        rareData()->setPreviousID(vm, structure);
+    else
+        m_previousOrRareData.set(vm, this, structure);
 }
 
 ALWAYS_INLINE bool Structure::shouldConvertToPolyProto(const Structure* a, const Structure* b)
index a40294d..b5a98db 100644 (file)
@@ -40,12 +40,12 @@ const ClassInfo StructureRareData::s_info = { "StructureRareData", nullptr, null
 
 Structure* StructureRareData::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
 {
-    return Structure::create(vm, globalObject, prototype, TypeInfo(StructureRareDataType, StructureFlags), info());
+    return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
 }
 
-StructureRareData* StructureRareData::create(VM& vm, StructureChain* chain)
+StructureRareData* StructureRareData::create(VM& vm, Structure* previous)
 {
-    StructureRareData* rareData = new (NotNull, allocateCell<StructureRareData>(vm.heap)) StructureRareData(vm, chain);
+    StructureRareData* rareData = new (NotNull, allocateCell<StructureRareData>(vm.heap)) StructureRareData(vm, previous);
     rareData->finishCreation(vm);
     return rareData;
 }
@@ -55,13 +55,13 @@ void StructureRareData::destroy(JSCell* cell)
     static_cast<StructureRareData*>(cell)->StructureRareData::~StructureRareData();
 }
 
-StructureRareData::StructureRareData(VM& vm, StructureChain* chain)
+StructureRareData::StructureRareData(VM& vm, Structure* previous)
     : JSCell(vm, vm.structureRareDataStructure.get())
     , m_maxOffset(invalidOffset)
     , m_transitionOffset(invalidOffset)
 {
-    if (chain)
-        m_cachedPrototypeChain.set(vm, this, chain);
+    if (previous)
+        m_previous.set(vm, this, previous);
 }
 
 void StructureRareData::visitChildren(JSCell* cell, SlotVisitor& visitor)
@@ -70,7 +70,7 @@ void StructureRareData::visitChildren(JSCell* cell, SlotVisitor& visitor)
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
 
     Base::visitChildren(thisObject, visitor);
-    visitor.append(thisObject->m_cachedPrototypeChain);
+    visitor.append(thisObject->m_previous);
     visitor.appendUnbarriered(thisObject->objectToStringValue());
     visitor.append(thisObject->m_cachedPropertyNameEnumerator);
     auto* cachedOwnKeys = thisObject->m_cachedOwnKeys.unvalidatedGet();
index fe903bb..07ed904 100644 (file)
@@ -35,7 +35,6 @@ namespace JSC {
 
 class JSPropertyNameEnumerator;
 class Structure;
-class StructureChain;
 class ObjectToStringAdaptiveInferredPropertyValueWatchpoint;
 class ObjectToStringAdaptiveStructureWatchpoint;
 
@@ -50,7 +49,7 @@ public:
         return &vm.structureRareDataSpace;
     }
 
-    static StructureRareData* create(VM&, StructureChain*);
+    static StructureRareData* create(VM&, Structure*);
 
     static constexpr bool needsDestruction = true;
     static void destroy(JSCell*);
@@ -59,11 +58,12 @@ public:
 
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
 
-    StructureChain* cachedPrototypeChain() const
+    Structure* previousID() const
     {
-        return m_cachedPrototypeChain.get();
+        return m_previous.get();
     }
-    void setCachedPrototypeChain(VM&, StructureChain*);
+    void setPreviousID(VM&, Structure*);
+    void clearPreviousID();
 
     JSString* objectToStringValue() const;
     void setObjectToStringValue(JSGlobalObject*, VM&, Structure* baseStructure, JSString* value, PropertySlot toStringTagSymbolSlot);
@@ -102,9 +102,9 @@ private:
 
     void clearObjectToStringValue();
 
-    StructureRareData(VM&, StructureChain*);
+    StructureRareData(VM&, Structure*);
 
-    WriteBarrier<StructureChain> m_cachedPrototypeChain;
+    WriteBarrier<Structure> m_previous;
     WriteBarrier<JSString> m_objectToStringValue;
     // FIXME: We should have some story for clearing these property names caches in GC.
     // https://bugs.webkit.org/show_bug.cgi?id=192659
index 94c49a8..e2fd504 100644 (file)
 
 namespace JSC {
 
-inline void StructureRareData::setCachedPrototypeChain(VM& vm, StructureChain* chain)
+inline void StructureRareData::setPreviousID(VM& vm, Structure* structure)
 {
-    m_cachedPrototypeChain.setMayBeNull(vm, this, chain);
+    m_previous.set(vm, this, structure);
+}
+
+inline void StructureRareData::clearPreviousID()
+{
+    m_previous.clear();
 }
 
 inline JSString* StructureRareData::objectToStringValue() const
index ad29209..f48928c 100644 (file)
@@ -150,7 +150,7 @@ class StructureTransitionTable {
         // We encode (2) and (3) into (1)'s empty bits since a pointer is 48bit and lower 3 bits are usable because of alignment.
         struct Key {
             friend struct Hash;
-            static_assert(OS_CONSTANT(EFFECTIVE_ADDRESS_WIDTH) <= 48);
+            static_assert(WTF_OS_CONSTANT_EFFECTIVE_ADDRESS_WIDTH <= 48);
             static constexpr uintptr_t isAdditionMask = 1ULL;
             static constexpr uintptr_t stringMask = ((1ULL << 48) - 1) & (~isAdditionMask);
             static constexpr unsigned attributesShift = 48;
index 7aacee6..cd0cd84 100644 (file)
@@ -2874,7 +2874,7 @@ EncodedJSValue JSC_HOST_CALL JSDollarVMHelper::functionGetStructureTransitionLis
         return JSValue::encode(jsNull());
     Vector<Structure*, 8> structures;
 
-    for (auto* structure = obj->structure(); structure; structure = structure->previousID(vm))
+    for (auto* structure = obj->structure(); structure; structure = structure->previousID())
         structures.append(structure);
 
     JSArray* result = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 0);
@@ -2888,8 +2888,8 @@ EncodedJSValue JSC_HOST_CALL JSDollarVMHelper::functionGetStructureTransitionLis
         RETURN_IF_EXCEPTION(scope, { });
         result->push(globalObject, JSValue(structure->maxOffset()));
         RETURN_IF_EXCEPTION(scope, { });
-        if (auto* transitionPropertyName = structure->transitionPropertyName())
-            result->push(globalObject, jsString(vm, String(*transitionPropertyName)));
+        if (structure->m_transitionPropertyName)
+            result->push(globalObject, jsString(vm, String(*structure->m_transitionPropertyName)));
         else
             result->push(globalObject, jsNull());
         RETURN_IF_EXCEPTION(scope, { });
index 2bff704..16ecdaa 100644 (file)
@@ -275,7 +275,7 @@ MacroAssemblerCodePtr<JSEntryPtrTag> WebAssemblyFunction::jsCallEntrypointSlow()
 
             stackLimitGPRIsClobbered = true;
             jit.emitLoadStructure(vm, scratchGPR, scratchGPR, stackLimitGPR);
-            jit.emitLoadClassInfoFromStructure(scratchGPR, scratchGPR);
+            jit.loadPtr(CCallHelpers::Address(scratchGPR, Structure::classInfoOffset()), scratchGPR);
 
             static_assert(std::is_final<WebAssemblyFunction>::value, "We do not check for subtypes below");
             static_assert(std::is_final<WebAssemblyWrapperFunction>::value, "We do not check for subtypes below");