Title: [245658] trunk/Source/_javascript_Core
Revision
245658
Author
ysuz...@apple.com
Date
2019-05-22 16:42:30 -0700 (Wed, 22 May 2019)

Log Message

[JSC] Shrink Metadata
https://bugs.webkit.org/show_bug.cgi?id=197940

Reviewed by Michael Saboff.

We get Metadata related data in Gmail and it turns out the following things.

1. At peak, MetadataTable eats a lot of bytes (30 MB - 50 MB, sometimes 70 MB while total Gmail footprint is 400 - 500 MB).
2. After full GC happens, most of Metadata is destroyed while some are kept. Still keeps 1 MB. But after the GC, # of MetadataTable eventually grows again.

If we shrink Metadata, we can reduce the peak memory footprint in Gmail.

This patch shrinks Metadata. This patch first focus on low hanging fruits: it does not include the change removing OSR exit JSValue in ValueProfile.
This patch uses fancy bit juggling & leverages nice data types to reduce Metadata, as follows.

1. ValueProfile is reduced from 32 to 24. It reduces Metadata using ValueProfile.
2. ArrayProfile is reduced from 16 to 12. Ditto.
3. OpCall::Metadata is reduced from 88 to 64.
4. OpGetById::Metadata is reduced from 56 to 40.
5. OpToThis::Metadata is reduced from 48 to 32.
6. OpNewObject::Metadata is reduced from 32 to 16.

According to the gathered data, it should reduce 1-2MB in steady state in Gmail, much more in peak memory, ~1 MB in the state just after full GC.
It also improves RAMification by 0.3% (6 runs).

* bytecode/ArrayProfile.cpp:
* bytecode/ArrayProfile.h:
(JSC::ArrayProfile::ArrayProfile):
(JSC::ArrayProfile::bytecodeOffset const): Deleted.
(JSC::ArrayProfile::isValid const): Deleted.
* bytecode/BytecodeList.rb:
* bytecode/CallLinkStatus.cpp:
(JSC::CallLinkStatus::computeFromLLInt):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::finishCreation):
(JSC::CodeBlock::finalizeLLIntInlineCaches):
(JSC::CodeBlock::getArrayProfile):
(JSC::CodeBlock::updateAllPredictionsAndCountLiveness):
(JSC::CodeBlock::dumpValueProfiles):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::valueProfileForArgument):
* bytecode/CodeBlockInlines.h:
(JSC::CodeBlock::forEachValueProfile):
(JSC::CodeBlock::forEachArrayProfile):
* bytecode/GetByIdMetadata.h:
We use ProtoLoad's JSObject's high bits to embed hitCountForLLIntCaching and mode, since they
are always zero for ProtoLoad mode.

(): Deleted.
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeFromLLInt):
* bytecode/LLIntCallLinkInfo.h:
(JSC::LLIntCallLinkInfo::isLinked const):
(JSC::LLIntCallLinkInfo::link):
(JSC::LLIntCallLinkInfo::unlink):
(JSC::LLIntCallLinkInfo::callee const):
(JSC::LLIntCallLinkInfo::lastSeenCallee const):
(JSC::LLIntCallLinkInfo::clearLastSeenCallee):
(JSC::LLIntCallLinkInfo::LLIntCallLinkInfo): Deleted.
(JSC::LLIntCallLinkInfo::isLinked): Deleted.
In LLIntCallLinkInfo, we always set the same value to lastSeenCallee and callee. But later, callee can be cleared.
It means that we can represent them in one value + cleared flag. We encode this flag into the lowest bit of the callee cell so
that we can make them one pointer. We also use PackedRawSentinelNode to get some space, and embed ArrayProfile into this space
to get further memory reduction.

* bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp:
(JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::clearLLIntGetByIdCache):
* bytecode/LazyOperandValueProfile.h:
(JSC::LazyOperandValueProfile::LazyOperandValueProfile):
(JSC::LazyOperandValueProfile::key const):
* bytecode/MetadataTable.h:
(JSC::MetadataTable::buffer):
* bytecode/ObjectAllocationProfile.h:
(JSC::ObjectAllocationProfileBase::offsetOfAllocator):
(JSC::ObjectAllocationProfileBase::offsetOfStructure):
(JSC::ObjectAllocationProfileBase::clear):
(JSC::ObjectAllocationProfileBase::visitAggregate):
(JSC::ObjectAllocationProfile::setPrototype):
(JSC::ObjectAllocationProfileWithPrototype::prototype):
(JSC::ObjectAllocationProfileWithPrototype::clear):
(JSC::ObjectAllocationProfileWithPrototype::visitAggregate):
(JSC::ObjectAllocationProfileWithPrototype::setPrototype):
(JSC::ObjectAllocationProfile::offsetOfAllocator): Deleted.
(JSC::ObjectAllocationProfile::offsetOfStructure): Deleted.
(JSC::ObjectAllocationProfile::offsetOfInlineCapacity): Deleted.
(JSC::ObjectAllocationProfile::ObjectAllocationProfile): Deleted.
(JSC::ObjectAllocationProfile::isNull): Deleted.
(JSC::ObjectAllocationProfile::structure): Deleted.
(JSC::ObjectAllocationProfile::prototype): Deleted.
(JSC::ObjectAllocationProfile::inlineCapacity): Deleted.
(JSC::ObjectAllocationProfile::clear): Deleted.
(JSC::ObjectAllocationProfile::visitAggregate): Deleted.
* bytecode/ObjectAllocationProfileInlines.h:
(JSC::ObjectAllocationProfileBase<Derived>::initializeProfile):
(JSC::ObjectAllocationProfileBase<Derived>::possibleDefaultPropertyCount):
(JSC::ObjectAllocationProfile::initializeProfile): Deleted.
(JSC::ObjectAllocationProfile::possibleDefaultPropertyCount): Deleted.
OpNewObject's ObjectAllocationProfile does not need to hold prototype. So we have two versions now, ObjectAllocationProfile and ObjectAllocationProfileWithPrototype
to cut one pointer. We also remove inline capacity since this can be retrieved from Structure.

* bytecode/Opcode.h:
* bytecode/ValueProfile.h:
(JSC::ValueProfileBase::ValueProfileBase):
(JSC::ValueProfileBase::totalNumberOfSamples const):
(JSC::ValueProfileBase::isSampledBefore const):
(JSC::ValueProfileBase::dump):
(JSC::ValueProfileBase::computeUpdatedPrediction):
(JSC::MinimalValueProfile::MinimalValueProfile):
(JSC::ValueProfileWithLogNumberOfBuckets::ValueProfileWithLogNumberOfBuckets):
(JSC::ValueProfile::ValueProfile):
(JSC::getValueProfileBytecodeOffset): Deleted.
Bytecode offset is no longer used. And sample count is not used effectively.

* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGOperations.cpp:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileCreateThis):
* ftl/FTLAbstractHeapRepository.h:
* jit/JITCall.cpp:
(JSC::JIT::compileSetupFrame):
* jit/JITCall32_64.cpp:
(JSC::JIT::compileSetupFrame):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_catch):
(JSC::JIT::emit_op_to_this):
(JSC::JIT::emit_op_create_this):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_catch):
(JSC::JIT::emit_op_create_this):
(JSC::JIT::emit_op_to_this):
* jit/JITOperations.cpp:
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_get_by_id):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::setupGetByIdPrototypeCache):
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
(JSC::LLInt::setUpCall):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/FunctionRareData.h:
* tools/HeapVerifier.cpp:
(JSC::HeapVerifier::validateJSCell):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (245657 => 245658)


--- trunk/Source/_javascript_Core/ChangeLog	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-05-22 23:42:30 UTC (rev 245658)
@@ -1,3 +1,151 @@
+2019-05-22  Yusuke Suzuki  <ysuz...@apple.com>
+
+        [JSC] Shrink Metadata
+        https://bugs.webkit.org/show_bug.cgi?id=197940
+
+        Reviewed by Michael Saboff.
+
+        We get Metadata related data in Gmail and it turns out the following things.
+
+        1. At peak, MetadataTable eats a lot of bytes (30 MB - 50 MB, sometimes 70 MB while total Gmail footprint is 400 - 500 MB).
+        2. After full GC happens, most of Metadata is destroyed while some are kept. Still keeps 1 MB. But after the GC, # of MetadataTable eventually grows again.
+
+        If we shrink Metadata, we can reduce the peak memory footprint in Gmail.
+
+        This patch shrinks Metadata. This patch first focus on low hanging fruits: it does not include the change removing OSR exit JSValue in ValueProfile.
+        This patch uses fancy bit juggling & leverages nice data types to reduce Metadata, as follows.
+
+        1. ValueProfile is reduced from 32 to 24. It reduces Metadata using ValueProfile.
+        2. ArrayProfile is reduced from 16 to 12. Ditto.
+        3. OpCall::Metadata is reduced from 88 to 64.
+        4. OpGetById::Metadata is reduced from 56 to 40.
+        5. OpToThis::Metadata is reduced from 48 to 32.
+        6. OpNewObject::Metadata is reduced from 32 to 16.
+
+        According to the gathered data, it should reduce 1-2MB in steady state in Gmail, much more in peak memory, ~1 MB in the state just after full GC.
+        It also improves RAMification by 0.3% (6 runs).
+
+        * bytecode/ArrayProfile.cpp:
+        * bytecode/ArrayProfile.h:
+        (JSC::ArrayProfile::ArrayProfile):
+        (JSC::ArrayProfile::bytecodeOffset const): Deleted.
+        (JSC::ArrayProfile::isValid const): Deleted.
+        * bytecode/BytecodeList.rb:
+        * bytecode/CallLinkStatus.cpp:
+        (JSC::CallLinkStatus::computeFromLLInt):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::finishCreation):
+        (JSC::CodeBlock::finalizeLLIntInlineCaches):
+        (JSC::CodeBlock::getArrayProfile):
+        (JSC::CodeBlock::updateAllPredictionsAndCountLiveness):
+        (JSC::CodeBlock::dumpValueProfiles):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::valueProfileForArgument):
+        * bytecode/CodeBlockInlines.h:
+        (JSC::CodeBlock::forEachValueProfile):
+        (JSC::CodeBlock::forEachArrayProfile):
+        * bytecode/GetByIdMetadata.h:
+        We use ProtoLoad's JSObject's high bits to embed hitCountForLLIntCaching and mode, since they
+        are always zero for ProtoLoad mode.
+
+        (): Deleted.
+        * bytecode/GetByIdStatus.cpp:
+        (JSC::GetByIdStatus::computeFromLLInt):
+        * bytecode/LLIntCallLinkInfo.h:
+        (JSC::LLIntCallLinkInfo::isLinked const):
+        (JSC::LLIntCallLinkInfo::link):
+        (JSC::LLIntCallLinkInfo::unlink):
+        (JSC::LLIntCallLinkInfo::callee const):
+        (JSC::LLIntCallLinkInfo::lastSeenCallee const):
+        (JSC::LLIntCallLinkInfo::clearLastSeenCallee):
+        (JSC::LLIntCallLinkInfo::LLIntCallLinkInfo): Deleted.
+        (JSC::LLIntCallLinkInfo::isLinked): Deleted.
+        In LLIntCallLinkInfo, we always set the same value to lastSeenCallee and callee. But later, callee can be cleared.
+        It means that we can represent them in one value + cleared flag. We encode this flag into the lowest bit of the callee cell so
+        that we can make them one pointer. We also use PackedRawSentinelNode to get some space, and embed ArrayProfile into this space
+        to get further memory reduction.
+
+        * bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp:
+        (JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::clearLLIntGetByIdCache):
+        * bytecode/LazyOperandValueProfile.h:
+        (JSC::LazyOperandValueProfile::LazyOperandValueProfile):
+        (JSC::LazyOperandValueProfile::key const):
+        * bytecode/MetadataTable.h:
+        (JSC::MetadataTable::buffer):
+        * bytecode/ObjectAllocationProfile.h:
+        (JSC::ObjectAllocationProfileBase::offsetOfAllocator):
+        (JSC::ObjectAllocationProfileBase::offsetOfStructure):
+        (JSC::ObjectAllocationProfileBase::clear):
+        (JSC::ObjectAllocationProfileBase::visitAggregate):
+        (JSC::ObjectAllocationProfile::setPrototype):
+        (JSC::ObjectAllocationProfileWithPrototype::prototype):
+        (JSC::ObjectAllocationProfileWithPrototype::clear):
+        (JSC::ObjectAllocationProfileWithPrototype::visitAggregate):
+        (JSC::ObjectAllocationProfileWithPrototype::setPrototype):
+        (JSC::ObjectAllocationProfile::offsetOfAllocator): Deleted.
+        (JSC::ObjectAllocationProfile::offsetOfStructure): Deleted.
+        (JSC::ObjectAllocationProfile::offsetOfInlineCapacity): Deleted.
+        (JSC::ObjectAllocationProfile::ObjectAllocationProfile): Deleted.
+        (JSC::ObjectAllocationProfile::isNull): Deleted.
+        (JSC::ObjectAllocationProfile::structure): Deleted.
+        (JSC::ObjectAllocationProfile::prototype): Deleted.
+        (JSC::ObjectAllocationProfile::inlineCapacity): Deleted.
+        (JSC::ObjectAllocationProfile::clear): Deleted.
+        (JSC::ObjectAllocationProfile::visitAggregate): Deleted.
+        * bytecode/ObjectAllocationProfileInlines.h:
+        (JSC::ObjectAllocationProfileBase<Derived>::initializeProfile):
+        (JSC::ObjectAllocationProfileBase<Derived>::possibleDefaultPropertyCount):
+        (JSC::ObjectAllocationProfile::initializeProfile): Deleted.
+        (JSC::ObjectAllocationProfile::possibleDefaultPropertyCount): Deleted.
+        OpNewObject's ObjectAllocationProfile does not need to hold prototype. So we have two versions now, ObjectAllocationProfile and ObjectAllocationProfileWithPrototype
+        to cut one pointer. We also remove inline capacity since this can be retrieved from Structure.
+
+        * bytecode/Opcode.h:
+        * bytecode/ValueProfile.h:
+        (JSC::ValueProfileBase::ValueProfileBase):
+        (JSC::ValueProfileBase::totalNumberOfSamples const):
+        (JSC::ValueProfileBase::isSampledBefore const):
+        (JSC::ValueProfileBase::dump):
+        (JSC::ValueProfileBase::computeUpdatedPrediction):
+        (JSC::MinimalValueProfile::MinimalValueProfile):
+        (JSC::ValueProfileWithLogNumberOfBuckets::ValueProfileWithLogNumberOfBuckets):
+        (JSC::ValueProfile::ValueProfile):
+        (JSC::getValueProfileBytecodeOffset): Deleted.
+        Bytecode offset is no longer used. And sample count is not used effectively.
+
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileCreateThis):
+        * ftl/FTLAbstractHeapRepository.h:
+        * jit/JITCall.cpp:
+        (JSC::JIT::compileSetupFrame):
+        * jit/JITCall32_64.cpp:
+        (JSC::JIT::compileSetupFrame):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_catch):
+        (JSC::JIT::emit_op_to_this):
+        (JSC::JIT::emit_op_create_this):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_catch):
+        (JSC::JIT::emit_op_create_this):
+        (JSC::JIT::emit_op_to_this):
+        * jit/JITOperations.cpp:
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emit_op_get_by_id):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::setupGetByIdPrototypeCache):
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        (JSC::LLInt::setUpCall):
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/FunctionRareData.h:
+        * tools/HeapVerifier.cpp:
+        (JSC::HeapVerifier::validateJSCell):
+
 2019-05-22  Ross Kirsling  <ross.kirsl...@sony.com>
 
         [ESNext] Implement support for Numeric Separators

Modified: trunk/Source/_javascript_Core/bytecode/ArrayProfile.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/ArrayProfile.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/ArrayProfile.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -33,10 +33,6 @@
 
 namespace JSC {
 
-#if !ASSERT_DISABLED
-const char* const ArrayProfile::s_typeName = "ArrayProfile";
-#endif
-
 // Keep in sync with the order of TypedArrayType.
 const ArrayModes typedArrayModes[NumberOfTypedArrayTypesExcludingDataView] = {
     Int8ArrayMode,

Modified: trunk/Source/_javascript_Core/bytecode/ArrayProfile.h (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/ArrayProfile.h	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/ArrayProfile.h	2019-05-22 23:42:30 UTC (rev 245658)
@@ -27,7 +27,6 @@
 
 #include "ConcurrentJSLock.h"
 #include "Structure.h"
-#include <wtf/SegmentedVector.h>
 
 namespace JSC {
 
@@ -194,21 +193,13 @@
     friend class CodeBlock;
 
 public:
-    ArrayProfile()
-        : ArrayProfile(std::numeric_limits<unsigned>::max())
-    {
-    }
-    
-    explicit ArrayProfile(unsigned bytecodeOffset)
-        : m_bytecodeOffset(bytecodeOffset)
-        , m_mayInterceptIndexedAccesses(false)
+    explicit ArrayProfile()
+        : m_mayInterceptIndexedAccesses(false)
         , m_usesOriginalArrayStructures(true)
         , m_didPerformFirstRunPruning(false)
     {
     }
     
-    unsigned bytecodeOffset() const { return m_bytecodeOffset; }
-    
     StructureID* addressOfLastSeenStructureID() { return &m_lastSeenStructureID; }
     ArrayModes* addressOfArrayModes() { return &m_observedArrayModes; }
     bool* addressOfMayStoreToHole() { return &m_mayStoreToHole; }
@@ -238,16 +229,11 @@
     CString briefDescription(const ConcurrentJSLocker&, CodeBlock*);
     CString briefDescriptionWithoutUpdating(const ConcurrentJSLocker&);
     
-#if !ASSERT_DISABLED
-    inline bool isValid() const { return m_typeName == s_typeName; }
-#endif
-
 private:
     friend class LLIntOffsetsExtractor;
     
     static Structure* polymorphicStructure() { return static_cast<Structure*>(reinterpret_cast<void*>(1)); }
     
-    unsigned m_bytecodeOffset;
     StructureID m_lastSeenStructureID { 0 };
     bool m_mayStoreToHole { false }; // This flag may become overloaded to indicate other special cases that were encountered during array access, as it depends on indexing type. Since we currently have basically just one indexing type (two variants of ArrayStorage), this flag for now just means exactly what its name implies.
     bool m_outOfBounds { false };
@@ -255,13 +241,7 @@
     bool m_usesOriginalArrayStructures : 1;
     bool m_didPerformFirstRunPruning : 1;
     ArrayModes m_observedArrayModes { 0 };
-
-#if !ASSERT_DISABLED
-    static const char* const s_typeName;
-    const char* m_typeName { s_typeName };
-#endif
 };
+static_assert(sizeof(ArrayProfile) == 12);
 
-typedef SegmentedVector<ArrayProfile, 4> ArrayProfileVector;
-
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.rb (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/BytecodeList.rb	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.rb	2019-05-22 23:42:30 UTC (rev 245658)
@@ -136,7 +136,7 @@
         srcDst: VirtualRegister,
     },
     metadata: {
-        cachedStructure: WriteBarrierBase[Structure],
+        cachedStructureID: StructureID,
         toThisStatus: ToThisStatus,
         profile: ValueProfile,
     }
@@ -414,8 +414,6 @@
         property: unsigned,
     },
     metadata: {
-        mode: GetByIdMode,
-        hitCountForLLIntCaching: unsigned,
         modeMetadata: GetByIdModeMetadata,
         profile: ValueProfile,
     }
@@ -706,7 +704,6 @@
     },
     metadata: {
         callLinkInfo: LLIntCallLinkInfo,
-        arrayProfile: ArrayProfile,
         profile: ValueProfile,
     }
 
@@ -719,7 +716,6 @@
     },
     metadata: {
         callLinkInfo: LLIntCallLinkInfo,
-        arrayProfile: ArrayProfile,
         profile: ValueProfile,
     }
 
@@ -732,7 +728,6 @@
     },
     metadata: {
         callLinkInfo: LLIntCallLinkInfo,
-        arrayProfile: ArrayProfile,
         profile: ValueProfile,
     }
 
@@ -787,7 +782,6 @@
     },
     metadata: {
         callLinkInfo: LLIntCallLinkInfo,
-        arrayProfile: ArrayProfile,
         profile: ValueProfile,
     }
 

Modified: trunk/Source/_javascript_Core/bytecode/CallLinkStatus.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/CallLinkStatus.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/CallLinkStatus.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -86,7 +86,7 @@
     }
     
     
-    return CallLinkStatus(callLinkInfo->lastSeenCallee.get());
+    return CallLinkStatus(callLinkInfo->lastSeenCallee());
 }
 
 CallLinkStatus CallLinkStatus::computeFor(

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -482,15 +482,10 @@
     // Bookkeep the strongly referenced module environments.
     HashSet<JSModuleEnvironment*> stronglyReferencedModuleEnvironments;
 
-    auto link_profile = [&](const auto& instruction, auto /*bytecode*/, auto& metadata) {
+    auto link_profile = [&](const auto& /*instruction*/, auto /*bytecode*/, auto& /*metadata*/) {
         m_numberOfNonArgumentValueProfiles++;
-        metadata.m_profile.m_bytecodeOffset = instruction.offset();
     };
 
-    auto link_arrayProfile = [&](const auto& instruction, auto /*bytecode*/, auto& metadata) {
-        metadata.m_arrayProfile.m_bytecodeOffset = instruction.offset();
-    };
-
     auto link_objectAllocationProfile = [&](const auto& /*instruction*/, auto bytecode, auto& metadata) {
         metadata.m_objectAllocationProfile.initializeProfile(vm, m_globalObject.get(), this, m_globalObject->objectPrototype(), bytecode.m_inlineCapacity);
     };
@@ -499,10 +494,6 @@
         metadata.m_arrayAllocationProfile.initializeIndexingMode(bytecode.m_recommendedIndexingType);
     };
 
-    auto link_hitCountForLLIntCaching = [&](const auto& /*instruction*/, auto /*bytecode*/, auto& metadata) {
-        metadata.m_hitCountForLLIntCaching = Options::prototypeHitCountForLLIntCaching();
-    };
-
 #define LINK_FIELD(__field) \
     WTF_LAZY_JOIN(link_, __field)(instruction, bytecode, metadata);
 
@@ -527,13 +518,13 @@
         OpcodeID opcodeID = instruction->opcodeID();
         m_bytecodeCost += opcodeLengths[opcodeID];
         switch (opcodeID) {
-        LINK(OpHasIndexedProperty, arrayProfile)
+        LINK(OpHasIndexedProperty)
 
-        LINK(OpCallVarargs, arrayProfile, profile)
-        LINK(OpTailCallVarargs, arrayProfile, profile)
-        LINK(OpTailCallForwardArguments, arrayProfile, profile)
-        LINK(OpConstructVarargs, arrayProfile, profile)
-        LINK(OpGetByVal, arrayProfile, profile)
+        LINK(OpCallVarargs, profile)
+        LINK(OpTailCallVarargs, profile)
+        LINK(OpTailCallForwardArguments, profile)
+        LINK(OpConstructVarargs, profile)
+        LINK(OpGetByVal, profile)
 
         LINK(OpGetDirectPname, profile)
         LINK(OpGetByIdWithThis, profile)
@@ -550,16 +541,16 @@
         LINK(OpBitnot, profile)
         LINK(OpBitxor, profile)
 
-        LINK(OpGetById, profile, hitCountForLLIntCaching)
+        LINK(OpGetById, profile)
 
-        LINK(OpCall, profile, arrayProfile)
-        LINK(OpTailCall, profile, arrayProfile)
-        LINK(OpCallEval, profile, arrayProfile)
-        LINK(OpConstruct, profile, arrayProfile)
+        LINK(OpCall, profile)
+        LINK(OpTailCall, profile)
+        LINK(OpCallEval, profile)
+        LINK(OpConstruct, profile)
 
-        LINK(OpInByVal, arrayProfile)
-        LINK(OpPutByVal, arrayProfile)
-        LINK(OpPutByValDirect, arrayProfile)
+        LINK(OpInByVal)
+        LINK(OpPutByVal)
+        LINK(OpPutByValDirect)
 
         LINK(OpNewArray)
         LINK(OpNewArrayWithSize)
@@ -1208,7 +1199,7 @@
         switch (curInstruction->opcodeID()) {
         case op_get_by_id: {
             auto& metadata = curInstruction->as<OpGetById>().metadata(this);
-            if (metadata.m_mode != GetByIdMode::Default)
+            if (metadata.m_modeMetadata.mode != GetByIdMode::Default)
                 break;
             StructureID oldStructureID = metadata.m_modeMetadata.defaultMode.structureID;
             if (!oldStructureID || vm.heap.isMarked(vm.heap.structureIDTable().get(oldStructureID)))
@@ -1252,11 +1243,13 @@
             break;
         case op_to_this: {
             auto& metadata = curInstruction->as<OpToThis>().metadata(this);
-            if (!metadata.m_cachedStructure || vm.heap.isMarked(metadata.m_cachedStructure.get()))
+            if (!metadata.m_cachedStructureID || vm.heap.isMarked(vm.heap.structureIDTable().get(metadata.m_cachedStructureID)))
                 break;
-            if (Options::verboseOSR())
-                dataLogF("Clearing LLInt to_this with structure %p.\n", metadata.m_cachedStructure.get());
-            metadata.m_cachedStructure.clear();
+            if (Options::verboseOSR()) {
+                Structure* structure = vm.heap.structureIDTable().get(metadata.m_cachedStructureID);
+                dataLogF("Clearing LLInt to_this with structure %p.\n", structure);
+            }
+            metadata.m_cachedStructureID = 0;
             metadata.m_toThisStatus = merge(metadata.m_toThisStatus, ToThisClearedByGC);
             break;
         }
@@ -1324,13 +1317,13 @@
     });
 
     forEachLLIntCallLinkInfo([&](LLIntCallLinkInfo& callLinkInfo) {
-        if (callLinkInfo.isLinked() && !vm.heap.isMarked(callLinkInfo.callee.get())) {
+        if (callLinkInfo.isLinked() && !vm.heap.isMarked(callLinkInfo.callee())) {
             if (Options::verboseOSR())
                 dataLog("Clearing LLInt call from ", *this, "\n");
             callLinkInfo.unlink();
         }
-        if (!!callLinkInfo.lastSeenCallee && !vm.heap.isMarked(callLinkInfo.lastSeenCallee.get()))
-            callLinkInfo.lastSeenCallee.clear();
+        if (callLinkInfo.lastSeenCallee() && !vm.heap.isMarked(callLinkInfo.lastSeenCallee()))
+            callLinkInfo.clearLastSeenCallee();
     });
 }
 
@@ -2575,17 +2568,24 @@
 {
     auto instruction = instructions().at(bytecodeOffset);
     switch (instruction->opcodeID()) {
-#define CASE(Op) \
+#define CASE1(Op) \
     case Op::opcodeID: \
         return &instruction->as<Op>().metadata(this).m_arrayProfile;
 
-    FOR_EACH_OPCODE_WITH_ARRAY_PROFILE(CASE)
-#undef CASE
+#define CASE2(Op) \
+    case Op::opcodeID: \
+        return &instruction->as<Op>().metadata(this).m_callLinkInfo.m_arrayProfile;
 
+    FOR_EACH_OPCODE_WITH_ARRAY_PROFILE(CASE1)
+    FOR_EACH_OPCODE_WITH_LLINT_CALL_LINK_INFO(CASE2)
+
+#undef CASE1
+#undef CASE2
+
     case OpGetById::opcodeID: {
         auto bytecode = instruction->as<OpGetById>();
         auto& metadata = bytecode.metadata(this);
-        if (metadata.m_mode == GetByIdMode::ArrayLength)
+        if (metadata.m_modeMetadata.mode == GetByIdMode::ArrayLength)
             return &metadata.m_modeMetadata.arrayLengthMode.arrayProfile;
         break;
     }
@@ -2633,16 +2633,17 @@
     numberOfLiveNonArgumentValueProfiles = 0;
     numberOfSamplesInProfiles = 0; // If this divided by ValueProfile::numberOfBuckets equals numberOfValueProfiles() then value profiles are full.
 
-    forEachValueProfile([&](ValueProfile& profile) {
+    forEachValueProfile([&](ValueProfile& profile, bool isArgument) {
         unsigned numSamples = profile.totalNumberOfSamples();
+        static_assert(ValueProfile::numberOfBuckets == 1);
         if (numSamples > ValueProfile::numberOfBuckets)
             numSamples = ValueProfile::numberOfBuckets; // We don't want profiles that are extremely hot to be given more weight.
         numberOfSamplesInProfiles += numSamples;
-        if (profile.m_bytecodeOffset < 0) {
+        if (isArgument) {
             profile.computeUpdatedPrediction(locker);
             return;
         }
-        if (profile.numberOfSamples() || profile.m_prediction != SpecNone)
+        if (profile.numberOfSamples() || profile.isSampledBefore())
             numberOfLiveNonArgumentValueProfiles++;
         profile.computeUpdatedPrediction(locker);
     });
@@ -2650,7 +2651,7 @@
     if (auto* rareData = m_rareData.get()) {
         for (auto& profileBucket : rareData->m_catchProfiles) {
             profileBucket->forEach([&] (ValueProfileAndOperand& profile) {
-                profile.m_profile.computeUpdatedPrediction(locker);
+                profile.computeUpdatedPrediction(locker);
             });
         }
     }
@@ -2800,12 +2801,11 @@
 void CodeBlock::dumpValueProfiles()
 {
     dataLog("ValueProfile for ", *this, ":\n");
-    forEachValueProfile([](ValueProfile& profile) {
-        if (profile.m_bytecodeOffset < 0) {
-            ASSERT(profile.m_bytecodeOffset == -1);
-            dataLogF("   arg = %u: ", i);
-        } else
-            dataLogF("   bc = %d: ", profile.m_bytecodeOffset);
+    forEachValueProfile([](ValueProfile& profile, bool isArgument) {
+        if (isArgument)
+            dataLogF("   arg: ");
+        else
+            dataLogF("   bc: ");
         if (!profile.numberOfSamples() && profile.m_prediction == SpecNone) {
             dataLogF("<empty>\n");
             continue;

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2019-05-22 23:42:30 UTC (rev 245658)
@@ -478,7 +478,6 @@
     {
         ASSERT(vm()->canUseJIT()); // This is only called from the various JIT compilers or places that first check numberOfArgumentValueProfiles before calling this.
         ValueProfile& result = m_argumentValueProfiles[argumentIndex];
-        ASSERT(result.m_bytecodeOffset == -1);
         return result;
     }
 
@@ -974,7 +973,7 @@
     VM* m_vm;
 
     const void* m_instructionsRawPointer { nullptr };
-    SentinelLinkedList<LLIntCallLinkInfo, BasicRawSentinelNode<LLIntCallLinkInfo>> m_incomingLLIntCalls;
+    SentinelLinkedList<LLIntCallLinkInfo, PackedRawSentinelNode<LLIntCallLinkInfo>> m_incomingLLIntCalls;
     StructureWatchpointMap m_llintGetByIdWatchpointMap;
     RefPtr<JITCode> m_jitCode;
 #if ENABLE(JIT)

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlockInlines.h (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/CodeBlockInlines.h	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlockInlines.h	2019-05-22 23:42:30 UTC (rev 245658)
@@ -35,11 +35,11 @@
 void CodeBlock::forEachValueProfile(const Functor& func)
 {
     for (unsigned i = 0; i < numberOfArgumentValueProfiles(); ++i)
-        func(valueProfileForArgument(i));
+        func(valueProfileForArgument(i), true);
 
     if (m_metadata) {
 #define VISIT(__op) \
-    m_metadata->forEach<__op>([&] (auto& metadata) { func(metadata.m_profile); });
+    m_metadata->forEach<__op>([&] (auto& metadata) { func(metadata.m_profile, false); });
 
         FOR_EACH_OPCODE_WITH_VALUE_PROFILE(VISIT)
 
@@ -53,16 +53,21 @@
 {
     if (m_metadata) {
         m_metadata->forEach<OpGetById>([&] (auto& metadata) {
-            if (metadata.m_mode == GetByIdMode::ArrayLength)
+            if (metadata.m_modeMetadata.mode == GetByIdMode::ArrayLength)
                 func(metadata.m_modeMetadata.arrayLengthMode.arrayProfile);
         });
 
-#define VISIT(__op) \
+#define VISIT1(__op) \
     m_metadata->forEach<__op>([&] (auto& metadata) { func(metadata.m_arrayProfile); });
 
-        FOR_EACH_OPCODE_WITH_ARRAY_PROFILE(VISIT)
+#define VISIT2(__op) \
+    m_metadata->forEach<__op>([&] (auto& metadata) { func(metadata.m_callLinkInfo.m_arrayProfile); });
 
-#undef VISIT
+        FOR_EACH_OPCODE_WITH_ARRAY_PROFILE(VISIT1)
+        FOR_EACH_OPCODE_WITH_LLINT_CALL_LINK_INFO(VISIT2)
+
+#undef VISIT1
+#undef VISIT2
     }
 }
 

Modified: trunk/Source/_javascript_Core/bytecode/GetByIdMetadata.h (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/GetByIdMetadata.h	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/GetByIdMetadata.h	2019-05-22 23:42:30 UTC (rev 245658)
@@ -28,34 +28,134 @@
 namespace JSC {
 
 enum class GetByIdMode : uint8_t {
-    Default = 0,
-    Unset = 1,
-    ProtoLoad = 2,
+    ProtoLoad = 0, // This must be zero to reuse the higher bits of the pointer as this ProtoLoad mode.
+    Default = 1,
+    Unset = 2,
     ArrayLength = 3,
 };
 
+struct GetByIdModeMetadataDefault {
+    StructureID structureID;
+    PropertyOffset cachedOffset;
+    unsigned padding1;
+};
+static_assert(sizeof(GetByIdModeMetadataDefault) == 12);
+
+struct GetByIdModeMetadataUnset {
+    StructureID structureID;
+    unsigned padding1;
+    unsigned padding2;
+};
+static_assert(sizeof(GetByIdModeMetadataUnset) == 12);
+
+struct GetByIdModeMetadataArrayLength {
+    ArrayProfile arrayProfile;
+};
+static_assert(sizeof(GetByIdModeMetadataArrayLength) == 12);
+
+struct GetByIdModeMetadataProtoLoad {
+    StructureID structureID;
+    PropertyOffset cachedOffset;
+    JSObject* cachedSlot;
+};
+#if CPU(LITTLE_ENDIAN) && CPU(ADDRESS64)
+static_assert(sizeof(GetByIdModeMetadataProtoLoad) == 16);
+#endif
+
+// In 64bit Little endian architecture, this union shares ProtoLoad's JSObject* cachedSlot with "hitCountForLLIntCaching" and "mode".
+// This is possible because these values must be zero if we use ProtoLoad mode.
+#if CPU(LITTLE_ENDIAN) && CPU(ADDRESS64)
 union GetByIdModeMetadata {
     GetByIdModeMetadata()
-    { }
+    {
+        defaultMode.structureID = 0;
+        defaultMode.cachedOffset = 0;
+        defaultMode.padding1 = 0;
+        mode = GetByIdMode::Default;
+        hitCountForLLIntCaching = Options::prototypeHitCountForLLIntCaching();
+    }
 
-    struct Default {
-        StructureID structureID;
-        PropertyOffset cachedOffset;
-    } defaultMode;
+    void clearToDefaultModeWithoutCache();
+    void setUnsetMode(Structure*);
+    void setArrayLengthMode();
+    void setProtoLoadMode(Structure*, PropertyOffset, JSObject*);
 
-    struct Unset {
-        StructureID structureID;
-    } unsetMode;
+    struct {
+        uint32_t padding1;
+        uint32_t padding2;
+        uint32_t padding3;
+        uint16_t padding4;
+        GetByIdMode mode;
+        uint8_t hitCountForLLIntCaching; // This must be zero when we use ProtoLoad mode.
+    };
+    GetByIdModeMetadataDefault defaultMode;
+    GetByIdModeMetadataUnset unsetMode;
+    GetByIdModeMetadataArrayLength arrayLengthMode;
+    GetByIdModeMetadataProtoLoad protoLoadMode;
+};
+static_assert(sizeof(GetByIdModeMetadata) == 16);
+#else
+struct GetByIdModeMetadata {
+    GetByIdModeMetadata()
+    {
+        defaultMode.structureID = 0;
+        defaultMode.cachedOffset = 0;
+        defaultMode.padding1 = 0;
+        mode = GetByIdMode::Default;
+        hitCountForLLIntCaching = Options::prototypeHitCountForLLIntCaching();
+    }
 
-    struct ProtoLoad {
-        StructureID structureID;
-        PropertyOffset cachedOffset;
-        JSObject* cachedSlot;
-    } protoLoadMode;
+    void clearToDefaultModeWithoutCache();
+    void setUnsetMode(Structure*);
+    void setArrayLengthMode();
+    void setProtoLoadMode(Structure*, PropertyOffset, JSObject*);
 
-    struct ArrayLength {
-        ArrayProfile arrayProfile;
-    } arrayLengthMode;
+    union {
+        GetByIdModeMetadataDefault defaultMode;
+        GetByIdModeMetadataUnset unsetMode;
+        GetByIdModeMetadataArrayLength arrayLengthMode;
+        GetByIdModeMetadataProtoLoad protoLoadMode;
+    };
+    GetByIdMode mode;
+    uint8_t hitCountForLLIntCaching;
 };
+#endif
 
+inline void GetByIdModeMetadata::clearToDefaultModeWithoutCache()
+{
+    mode = GetByIdMode::Default;
+    defaultMode.structureID = 0;
+    defaultMode.cachedOffset = 0;
+}
+
+inline void GetByIdModeMetadata::setUnsetMode(Structure* structure)
+{
+    mode = GetByIdMode::Unset;
+    unsetMode.structureID = structure->id();
+}
+
+inline void GetByIdModeMetadata::setArrayLengthMode()
+{
+    mode = GetByIdMode::ArrayLength;
+    new (&arrayLengthMode.arrayProfile) ArrayProfile;
+    // Prevent the prototype cache from ever happening.
+    hitCountForLLIntCaching = 0;
+}
+
+inline void GetByIdModeMetadata::setProtoLoadMode(Structure* structure, PropertyOffset offset, JSObject* cachedSlot)
+{
+    mode = GetByIdMode::ProtoLoad; // This must be first set. In 64bit architecture, this field is shared with protoLoadMode.cachedSlot.
+    protoLoadMode.structureID = structure->id();
+    protoLoadMode.cachedOffset = offset;
+    // We know that this pointer will remain valid because it will be cleared by either a watchpoint fire or
+    // during GC when we clear the LLInt caches.
+    protoLoadMode.cachedSlot = cachedSlot;
+
+    ASSERT(mode == GetByIdMode::ProtoLoad);
+    ASSERT(!hitCountForLLIntCaching);
+    ASSERT(protoLoadMode.structureID == structure->id());
+    ASSERT(protoLoadMode.cachedOffset == offset);
+    ASSERT(protoLoadMode.cachedSlot == cachedSlot);
+}
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/bytecode/GetByIdStatus.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/GetByIdStatus.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/GetByIdStatus.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -64,7 +64,7 @@
         auto& metadata = instruction->as<OpGetById>().metadata(profiledBlock);
         // FIXME: We should not just bail if we see a get_by_id_proto_load.
         // https://bugs.webkit.org/show_bug.cgi?id=158039
-        if (metadata.m_mode != GetByIdMode::Default)
+        if (metadata.m_modeMetadata.mode != GetByIdMode::Default)
             return GetByIdStatus(NoInformation, false);
         structureID = metadata.m_modeMetadata.defaultMode.structureID;
         break;

Modified: trunk/Source/_javascript_Core/bytecode/LLIntCallLinkInfo.h (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/LLIntCallLinkInfo.h	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/LLIntCallLinkInfo.h	2019-05-22 23:42:30 UTC (rev 245658)
@@ -34,10 +34,13 @@
 
 struct Instruction;
 
-struct LLIntCallLinkInfo : public BasicRawSentinelNode<LLIntCallLinkInfo> {
-    LLIntCallLinkInfo()
-    {
-    }
+class LLIntCallLinkInfo : public PackedRawSentinelNode<LLIntCallLinkInfo> {
+public:
+    friend class LLIntOffsetsExtractor;
+
+    static constexpr uintptr_t unlinkedBit = 0x1;
+
+    LLIntCallLinkInfo() = default;
     
     ~LLIntCallLinkInfo()
     {
@@ -45,19 +48,49 @@
             remove();
     }
     
-    bool isLinked() { return !!callee; }
+    bool isLinked() const { return !(m_calleeOrLastSeenCalleeWithLinkBit & unlinkedBit); }
     
+
+    void link(VM& vm, JSCell* owner, JSObject* callee, MacroAssemblerCodePtr<JSEntryPtrTag> codePtr)
+    {
+        if (isOnList())
+            remove();
+        m_calleeOrLastSeenCalleeWithLinkBit = bitwise_cast<uintptr_t>(callee);
+        vm.heap.writeBarrier(owner, callee);
+        m_machineCodeTarget = codePtr;
+    }
+
     void unlink()
     {
-        callee.clear();
-        machineCodeTarget = MacroAssemblerCodePtr<JSEntryPtrTag>();
+        // Make link invalidated. It works because LLInt tests the given callee with this pointer. But it is still valid as lastSeenCallee!
+        m_calleeOrLastSeenCalleeWithLinkBit |= unlinkedBit;
+        m_machineCodeTarget = MacroAssemblerCodePtr<JSEntryPtrTag>();
         if (isOnList())
             remove();
     }
-    
-    WriteBarrier<JSObject> callee;
-    WriteBarrier<JSObject> lastSeenCallee;
-    MacroAssemblerCodePtr<JSEntryPtrTag> machineCodeTarget;
+
+    JSObject* callee() const
+    {
+        if (!isLinked())
+            return nullptr;
+        return bitwise_cast<JSObject*>(m_calleeOrLastSeenCalleeWithLinkBit);
+    }
+
+    JSObject* lastSeenCallee() const
+    {
+        return bitwise_cast<JSObject*>(m_calleeOrLastSeenCalleeWithLinkBit & ~unlinkedBit);
+    }
+
+    void clearLastSeenCallee()
+    {
+        m_calleeOrLastSeenCalleeWithLinkBit = unlinkedBit;
+    }
+
+    ArrayProfile m_arrayProfile;
+
+private:
+    uintptr_t m_calleeOrLastSeenCalleeWithLinkBit { unlinkedBit };
+    MacroAssemblerCodePtr<JSEntryPtrTag> m_machineCodeTarget;
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -65,9 +65,8 @@
 
 void LLIntPrototypeLoadAdaptiveStructureWatchpoint::clearLLIntGetByIdCache(OpGetById::Metadata& metadata)
 {
-    metadata.m_mode = GetByIdMode::Default;
-    metadata.m_modeMetadata.defaultMode.cachedOffset = 0;
-    metadata.m_modeMetadata.defaultMode.structureID = 0;
+    // Keep hitCountForLLIntCaching value.
+    metadata.m_modeMetadata.clearToDefaultModeWithoutCache();
 }
 
 

Modified: trunk/Source/_javascript_Core/bytecode/LazyOperandValueProfile.h (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/LazyOperandValueProfile.h	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/LazyOperandValueProfile.h	2019-05-22 23:42:30 UTC (rev 245658)
@@ -129,17 +129,18 @@
     }
     
     explicit LazyOperandValueProfile(const LazyOperandValueProfileKey& key)
-        : MinimalValueProfile(key.bytecodeOffset())
-        , m_operand(key.operand())
+        : MinimalValueProfile()
+        , m_key(key)
     {
     }
     
     LazyOperandValueProfileKey key() const
     {
-        return LazyOperandValueProfileKey(m_bytecodeOffset, m_operand);
+        return m_key;
     }
     
     VirtualRegister m_operand;
+    LazyOperandValueProfileKey m_key;
     
     typedef SegmentedVector<LazyOperandValueProfile, 8> List;
 };

Modified: trunk/Source/_javascript_Core/bytecode/MetadataTable.h (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/MetadataTable.h	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/MetadataTable.h	2019-05-22 23:42:30 UTC (rev 245658)
@@ -88,11 +88,6 @@
         return refCount() == 1;
     }
 
-    UnlinkedMetadataTable::Offset* buffer()
-    {
-        return bitwise_cast<UnlinkedMetadataTable::Offset*>(this);
-    }
-
 private:
     MetadataTable(UnlinkedMetadataTable&);
 
@@ -101,6 +96,11 @@
         return *bitwise_cast<UnlinkedMetadataTable::LinkingData*>((bitwise_cast<uint8_t*>(this) - sizeof(UnlinkedMetadataTable::LinkingData)));
     }
 
+    UnlinkedMetadataTable::Offset* buffer()
+    {
+        return bitwise_cast<UnlinkedMetadataTable::Offset*>(this);
+    }
+
     ALWAYS_INLINE uint8_t* getImpl(unsigned i)
     {
         return bitwise_cast<uint8_t*>(this) + buffer()[i];

Modified: trunk/Source/_javascript_Core/bytecode/ObjectAllocationProfile.h (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/ObjectAllocationProfile.h	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/ObjectAllocationProfile.h	2019-05-22 23:42:30 UTC (rev 245658)
@@ -35,17 +35,14 @@
 
 class FunctionRareData;
 
-class ObjectAllocationProfile {
+template<typename Derived>
+class ObjectAllocationProfileBase {
     friend class LLIntOffsetsExtractor;
 public:
-    static ptrdiff_t offsetOfAllocator() { return OBJECT_OFFSETOF(ObjectAllocationProfile, m_allocator); }
-    static ptrdiff_t offsetOfStructure() { return OBJECT_OFFSETOF(ObjectAllocationProfile, m_structure); }
-    static ptrdiff_t offsetOfInlineCapacity() { return OBJECT_OFFSETOF(ObjectAllocationProfile, m_inlineCapacity); }
+    static ptrdiff_t offsetOfAllocator() { return OBJECT_OFFSETOF(ObjectAllocationProfileBase, m_allocator); }
+    static ptrdiff_t offsetOfStructure() { return OBJECT_OFFSETOF(ObjectAllocationProfileBase, m_structure); }
 
-    ObjectAllocationProfile()
-        : m_inlineCapacity(0)
-    {
-    }
+    ObjectAllocationProfileBase() = default;
 
     bool isNull() { return !m_structure; }
 
@@ -58,6 +55,45 @@
         WTF::loadLoadFence();
         return structure;
     }
+
+protected:
+    void clear()
+    {
+        m_allocator = Allocator();
+        m_structure.clear();
+        ASSERT(isNull());
+    }
+
+    void visitAggregate(SlotVisitor& visitor)
+    {
+        visitor.append(m_structure);
+    }
+
+private:
+    unsigned possibleDefaultPropertyCount(VM&, JSObject* prototype);
+
+    Allocator m_allocator; // Precomputed to make things easier for generated code.
+    WriteBarrier<Structure> m_structure;
+};
+
+class ObjectAllocationProfile : public ObjectAllocationProfileBase<ObjectAllocationProfile> {
+public:
+    using Base = ObjectAllocationProfileBase<ObjectAllocationProfile>;
+
+    ObjectAllocationProfile() = default;
+
+    using Base::clear;
+    using Base::visitAggregate;
+
+    void setPrototype(VM&, JSCell*, JSObject*) { }
+};
+
+class ObjectAllocationProfileWithPrototype : public ObjectAllocationProfileBase<ObjectAllocationProfileWithPrototype> {
+public:
+    using Base = ObjectAllocationProfileBase<ObjectAllocationProfileWithPrototype>;
+
+    ObjectAllocationProfileWithPrototype() = default;
+
     JSObject* prototype()
     {
         JSObject* prototype = m_prototype.get();
@@ -64,31 +100,29 @@
         WTF::loadLoadFence();
         return prototype;
     }
-    unsigned inlineCapacity() { return m_inlineCapacity; }
 
-
     void clear()
     {
-        m_allocator = Allocator();
-        m_structure.clear();
+        Base::clear();
         m_prototype.clear();
-        m_inlineCapacity = 0;
         ASSERT(isNull());
     }
 
     void visitAggregate(SlotVisitor& visitor)
     {
-        visitor.append(m_structure);
+        Base::visitAggregate(visitor);
         visitor.append(m_prototype);
     }
 
+    void setPrototype(VM& vm, JSCell* owner, JSObject* object)
+    {
+        m_prototype.set(vm, owner, object);
+    }
+
 private:
-    unsigned possibleDefaultPropertyCount(VM&, JSObject* prototype);
-
-    Allocator m_allocator; // Precomputed to make things easier for generated code.
-    WriteBarrier<Structure> m_structure;
     WriteBarrier<JSObject> m_prototype;
-    unsigned m_inlineCapacity;
 };
 
+
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/bytecode/ObjectAllocationProfileInlines.h (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/ObjectAllocationProfileInlines.h	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/ObjectAllocationProfileInlines.h	2019-05-22 23:42:30 UTC (rev 245658)
@@ -31,12 +31,11 @@
 
 namespace JSC {
 
-ALWAYS_INLINE void ObjectAllocationProfile::initializeProfile(VM& vm, JSGlobalObject* globalObject, JSCell* owner, JSObject* prototype, unsigned inferredInlineCapacity, JSFunction* constructor, FunctionRareData* functionRareData)
+template<typename Derived>
+ALWAYS_INLINE void ObjectAllocationProfileBase<Derived>::initializeProfile(VM& vm, JSGlobalObject* globalObject, JSCell* owner, JSObject* prototype, unsigned inferredInlineCapacity, JSFunction* constructor, FunctionRareData* functionRareData)
 {
     ASSERT(!m_allocator);
     ASSERT(!m_structure);
-    ASSERT(!m_prototype);
-    ASSERT(!m_inlineCapacity);
 
     // FIXME: Teach create_this's fast path how to allocate poly
     // proto objects: https://bugs.webkit.org/show_bug.cgi?id=177517
@@ -56,8 +55,7 @@
             RELEASE_ASSERT(structure->typeInfo().type() == FinalObjectType);
             m_allocator = Allocator();
             m_structure.set(vm, owner, structure);
-            m_prototype.set(vm, owner, prototype);
-            m_inlineCapacity = structure->inlineCapacity();
+            static_cast<Derived*>(this)->setPrototype(vm, owner, prototype);
             return;
         }
 
@@ -138,11 +136,11 @@
     WTF::storeStoreFence();
 
     m_structure.set(vm, owner, structure);
-    m_prototype.set(vm, owner, prototype);
-    m_inlineCapacity = inlineCapacity;
+    static_cast<Derived*>(this)->setPrototype(vm, owner, prototype);
 }
 
-ALWAYS_INLINE unsigned ObjectAllocationProfile::possibleDefaultPropertyCount(VM& vm, JSObject* prototype)
+template<typename Derived>
+ALWAYS_INLINE unsigned ObjectAllocationProfileBase<Derived>::possibleDefaultPropertyCount(VM& vm, JSObject* prototype)
 {
     if (prototype == prototype->globalObject(vm)->objectPrototype())
         return 0;

Modified: trunk/Source/_javascript_Core/bytecode/Opcode.h (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/Opcode.h	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/Opcode.h	2019-05-22 23:42:30 UTC (rev 245658)
@@ -111,10 +111,6 @@
     macro(OpTailCallForwardArguments) \
     macro(OpConstructVarargs) \
     macro(OpGetByVal) \
-    macro(OpCall) \
-    macro(OpTailCall) \
-    macro(OpCallEval) \
-    macro(OpConstruct) \
     macro(OpInByVal) \
     macro(OpPutByVal) \
     macro(OpPutByValDirect) \

Modified: trunk/Source/_javascript_Core/bytecode/ValueProfile.h (245657 => 245658)


--- trunk/Source/_javascript_Core/bytecode/ValueProfile.h	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/bytecode/ValueProfile.h	2019-05-22 23:42:30 UTC (rev 245658)
@@ -44,19 +44,11 @@
     static const unsigned totalNumberOfBuckets = numberOfBuckets + numberOfSpecFailBuckets;
     
     ValueProfileBase()
-        : m_bytecodeOffset(-1)
     {
         for (unsigned i = 0; i < totalNumberOfBuckets; ++i)
             m_buckets[i] = JSValue::encode(JSValue());
     }
     
-    ValueProfileBase(int bytecodeOffset)
-        : m_bytecodeOffset(bytecodeOffset)
-    {
-        for (unsigned i = 0; i < totalNumberOfBuckets; ++i)
-            m_buckets[i] = JSValue::encode(JSValue());
-    }
-    
     EncodedJSValue* specFailBucket(unsigned i)
     {
         ASSERT(numberOfBuckets + i < totalNumberOfBuckets);
@@ -86,8 +78,10 @@
     
     unsigned totalNumberOfSamples() const
     {
-        return numberOfSamples() + m_numberOfSamplesInPrediction;
+        return numberOfSamples() + isSampledBefore();
     }
+
+    bool isSampledBefore() const { return m_prediction != SpecNone; }
     
     bool isLive() const
     {
@@ -109,7 +103,7 @@
     
     void dump(PrintStream& out)
     {
-        out.print("samples = ", totalNumberOfSamples(), " prediction = ", SpeculationDump(m_prediction));
+        out.print("sampled before = ", isSampledBefore(), " live samples = ", numberOfSamples(), " prediction = ", SpeculationDump(m_prediction));
         bool first = true;
         for (unsigned i = 0; i < totalNumberOfBuckets; ++i) {
             JSValue value = JSValue::decode(m_buckets[i]);
@@ -133,7 +127,6 @@
             if (!value)
                 continue;
             
-            m_numberOfSamplesInPrediction++;
             mergeSpeculation(m_prediction, speculationFromValue(value));
             
             m_buckets[i] = JSValue::encode(JSValue());
@@ -142,17 +135,13 @@
         return m_prediction;
     }
     
-    int m_bytecodeOffset; // -1 for prologue
-    unsigned m_numberOfSamplesInPrediction { 0 };
-    
+    EncodedJSValue m_buckets[totalNumberOfBuckets];
+
     SpeculatedType m_prediction { SpecNone };
-    
-    EncodedJSValue m_buckets[totalNumberOfBuckets];
 };
 
 struct MinimalValueProfile : public ValueProfileBase<0> {
     MinimalValueProfile(): ValueProfileBase<0>() { }
-    MinimalValueProfile(int bytecodeOffset): ValueProfileBase<0>(bytecodeOffset) { }
 };
 
 template<unsigned logNumberOfBucketsArgument>
@@ -163,23 +152,12 @@
         : ValueProfileBase<1 << logNumberOfBucketsArgument>()
     {
     }
-    ValueProfileWithLogNumberOfBuckets(int bytecodeOffset)
-        : ValueProfileBase<1 << logNumberOfBucketsArgument>(bytecodeOffset)
-    {
-    }
 };
 
 struct ValueProfile : public ValueProfileWithLogNumberOfBuckets<0> {
     ValueProfile() : ValueProfileWithLogNumberOfBuckets<0>() { }
-    ValueProfile(int bytecodeOffset) : ValueProfileWithLogNumberOfBuckets<0>(bytecodeOffset) { }
 };
 
-template<typename T>
-inline int getValueProfileBytecodeOffset(T* valueProfile)
-{
-    return valueProfile->m_bytecodeOffset;
-}
-
 // This is a mini value profile to catch pathologies. It is a counter that gets
 // incremented when we take the slow path on any instruction.
 struct RareCaseProfile {
@@ -198,8 +176,7 @@
     return rareCaseProfile->m_bytecodeOffset;
 }
 
-struct ValueProfileAndOperand {
-    ValueProfile m_profile;
+struct ValueProfileAndOperand : public ValueProfile {
     int m_operand;
 };
 

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -4795,7 +4795,10 @@
         case op_to_this: {
             Node* op1 = getThis();
             auto& metadata = currentInstruction->as<OpToThis>().metadata(codeBlock);
-            Structure* cachedStructure = metadata.m_cachedStructure.get();
+            StructureID cachedStructureID = metadata.m_cachedStructureID;
+            Structure* cachedStructure = nullptr;
+            if (cachedStructureID)
+                cachedStructure = m_vm->heap.structureIDTable().get(cachedStructureID);
             if (metadata.m_toThisStatus != ToThisOK
                 || !cachedStructure
                 || cachedStructure->classInfo()->methodTable.toThis != JSObject::info()->methodTable.toThis
@@ -6011,7 +6014,7 @@
 
                 buffer->forEach([&] (ValueProfileAndOperand& profile) {
                     VirtualRegister operand(profile.m_operand);
-                    SpeculatedType prediction = profile.m_profile.computeUpdatedPrediction(locker);
+                    SpeculatedType prediction = profile.computeUpdatedPrediction(locker);
                     if (operand.isLocal())
                         localPredictions.append(prediction);
                     else {

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -355,7 +355,7 @@
     if (constructor->type() == JSFunctionType && jsCast<JSFunction*>(constructor)->canUseAllocationProfile()) {
         auto rareData = jsCast<JSFunction*>(constructor)->ensureRareDataAndAllocationProfile(exec, inlineCapacity);
         scope.releaseAssertNoException();
-        ObjectAllocationProfile* allocationProfile = rareData->objectAllocationProfile();
+        ObjectAllocationProfileWithPrototype* allocationProfile = rareData->objectAllocationProfile();
         Structure* structure = allocationProfile->structure();
         JSObject* result = constructEmptyObject(exec, structure);
         if (structure->hasPolyProto()) {

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -12565,14 +12565,13 @@
     slowPath.append(m_jit.branchIfNotFunction(calleeGPR));
     m_jit.loadPtr(JITCompiler::Address(calleeGPR, JSFunction::offsetOfRareData()), rareDataGPR);
     slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, rareDataGPR));
-    m_jit.loadPtr(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorGPR);
-    m_jit.loadPtr(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureGPR);
+    m_jit.loadPtr(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfileWithPrototype::offsetOfAllocator()), allocatorGPR);
+    m_jit.loadPtr(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfileWithPrototype::offsetOfStructure()), structureGPR);
 
     auto butterfly = TrustedImmPtr(nullptr);
     emitAllocateJSObject(resultGPR, JITAllocator::variable(), allocatorGPR, structureGPR, butterfly, scratchGPR, slowPath);
 
-    m_jit.loadPtr(JITCompiler::Address(calleeGPR, JSFunction::offsetOfRareData()), rareDataGPR);
-    m_jit.load32(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfInlineCapacity()), inlineCapacityGPR);
+    m_jit.load8(JITCompiler::Address(structureGPR, Structure::inlineCapacityOffset()), inlineCapacityGPR);
     m_jit.emitInitializeInlineStorage(resultGPR, inlineCapacityGPR);
     m_jit.mutatorFence(*m_jit.vm());
 

Modified: trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h (245657 => 245658)


--- trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h	2019-05-22 23:42:30 UTC (rev 245658)
@@ -57,8 +57,8 @@
     macro(DirectArguments_minCapacity, DirectArguments::offsetOfMinCapacity()) \
     macro(DirectArguments_mappedArguments, DirectArguments::offsetOfMappedArguments()) \
     macro(DirectArguments_modifiedArgumentsDescriptor, DirectArguments::offsetOfModifiedArgumentsDescriptor()) \
-    macro(FunctionRareData_allocator, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()) \
-    macro(FunctionRareData_structure, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()) \
+    macro(FunctionRareData_allocator, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfileWithPrototype::offsetOfAllocator()) \
+    macro(FunctionRareData_structure, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfileWithPrototype::offsetOfStructure()) \
     macro(GetterSetter_getter, GetterSetter::offsetOfGetter()) \
     macro(GetterSetter_setter, GetterSetter::offsetOfSetter()) \
     macro(JSArrayBufferView_length, JSArrayBufferView::offsetOfLength()) \

Modified: trunk/Source/_javascript_Core/jit/JITCall.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/jit/JITCall.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/jit/JITCall.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -69,7 +69,7 @@
         emitGetVirtualRegister(registerOffset + CallFrame::argumentOffsetIncludingThis(0), regT0);
         Jump done = branchIfNotCell(regT0);
         load32(Address(regT0, JSCell::structureIDOffset()), regT0);
-        store32(regT0, metadata.m_arrayProfile.addressOfLastSeenStructureID());
+        store32(regT0, metadata.m_callLinkInfo.m_arrayProfile.addressOfLastSeenStructureID());
         done.link(this);
     }
 

Modified: trunk/Source/_javascript_Core/jit/JITCall32_64.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/jit/JITCall32_64.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/jit/JITCall32_64.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -160,7 +160,7 @@
         emitLoad(registerOffset + CallFrame::argumentOffsetIncludingThis(0), regT0, regT1);
         Jump done = branchIfNotCell(regT0);
         load32(Address(regT1, JSCell::structureIDOffset()), regT1);
-        store32(regT1, metadata.m_arrayProfile.addressOfLastSeenStructureID());
+        store32(regT1, metadata.m_callLinkInfo.m_arrayProfile.addressOfLastSeenStructureID());
         done.link(this);
     }
 

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -707,7 +707,7 @@
         buffer->forEach([&] (ValueProfileAndOperand& profile) {
             JSValueRegs regs(regT0);
             emitGetVirtualRegister(profile.m_operand, regs);
-            emitValueProfilingSite(profile.m_profile);
+            emitValueProfilingSite(static_cast<ValueProfile&>(profile));
         });
     }
 #endif // ENABLE(DFG_JIT)
@@ -878,15 +878,13 @@
 {
     auto bytecode = currentInstruction->as<OpToThis>();
     auto& metadata = bytecode.metadata(m_codeBlock);
-    WriteBarrierBase<Structure>* cachedStructure = &metadata.m_cachedStructure;
+    StructureID* cachedStructureID = &metadata.m_cachedStructureID;
     emitGetVirtualRegister(bytecode.m_srcDst.offset(), regT1);
 
     emitJumpSlowCaseIfNotJSCell(regT1);
 
     addSlowCase(branchIfNotType(regT1, FinalObjectType));
-    loadPtr(cachedStructure, regT2);
-    addSlowCase(branchTestPtr(Zero, regT2));
-    load32(Address(regT2, Structure::structureIDOffset()), regT2);
+    load32(cachedStructureID, regT2);
     addSlowCase(branch32(NotEqual, Address(regT1, JSCell::structureIDOffset()), regT2));
 }
 
@@ -908,8 +906,8 @@
     addSlowCase(branchIfNotFunction(calleeReg));
     loadPtr(Address(calleeReg, JSFunction::offsetOfRareData()), rareDataReg);
     addSlowCase(branchTestPtr(Zero, rareDataReg));
-    loadPtr(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorReg);
-    loadPtr(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureReg);
+    loadPtr(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfileWithPrototype::offsetOfAllocator()), allocatorReg);
+    loadPtr(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfileWithPrototype::offsetOfStructure()), structureReg);
 
     loadPtr(cachedFunction, cachedFunctionReg);
     Jump hasSeenMultipleCallees = branchPtr(Equal, cachedFunctionReg, TrustedImmPtr(JSCell::seenMultipleCalleeObjects()));
@@ -919,9 +917,7 @@
     JumpList slowCases;
     auto butterfly = TrustedImmPtr(nullptr);
     emitAllocateJSObject(resultReg, JITAllocator::variable(), allocatorReg, structureReg, butterfly, scratchReg, slowCases);
-    emitGetVirtualRegister(callee, scratchReg);
-    loadPtr(Address(scratchReg, JSFunction::offsetOfRareData()), scratchReg);
-    load32(Address(scratchReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfInlineCapacity()), scratchReg);
+    load8(Address(structureReg, Structure::inlineCapacityOffset()), scratchReg);
     emitInitializeInlineStorage(resultReg, scratchReg);
     addSlowCase(slowCases);
     emitPutVirtualRegister(bytecode.m_dst.offset());

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -899,7 +899,7 @@
         buffer->forEach([&] (ValueProfileAndOperand& profile) {
             JSValueRegs regs(regT1, regT0);
             emitGetVirtualRegister(profile.m_operand, regs);
-            emitValueProfilingSite(profile.m_profile);
+            emitValueProfilingSite(static_cast<ValueProfile&>(profile));
         });
     }
 #endif // ENABLE(DFG_JIT)
@@ -1020,8 +1020,8 @@
     addSlowCase(branchIfNotFunction(calleeReg));
     loadPtr(Address(calleeReg, JSFunction::offsetOfRareData()), rareDataReg);
     addSlowCase(branchTestPtr(Zero, rareDataReg));
-    load32(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorReg);
-    loadPtr(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureReg);
+    load32(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfileWithPrototype::offsetOfAllocator()), allocatorReg);
+    loadPtr(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfileWithPrototype::offsetOfStructure()), structureReg);
 
     loadPtr(cachedFunction, cachedFunctionReg);
     Jump hasSeenMultipleCallees = branchPtr(Equal, cachedFunctionReg, TrustedImmPtr(JSCell::seenMultipleCalleeObjects()));
@@ -1031,9 +1031,7 @@
     JumpList slowCases;
     auto butterfly = TrustedImmPtr(nullptr);
     emitAllocateJSObject(resultReg, JITAllocator::variable(), allocatorReg, structureReg, butterfly, scratchReg, slowCases);
-    emitLoadPayload(callee, scratchReg);
-    loadPtr(Address(scratchReg, JSFunction::offsetOfRareData()), scratchReg);
-    load32(Address(scratchReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfInlineCapacity()), scratchReg);
+    load8(Address(structureReg, Structure::inlineCapacityOffset()), scratchReg);
     emitInitializeInlineStorage(resultReg, scratchReg);
     addSlowCase(slowCases);
     emitStoreCell(bytecode.m_dst.offset(), resultReg);
@@ -1043,7 +1041,7 @@
 {
     auto bytecode = currentInstruction->as<OpToThis>();
     auto& metadata = bytecode.metadata(m_codeBlock);
-    WriteBarrierBase<Structure>* cachedStructure = &metadata.m_cachedStructure;
+    StructureID* cachedStructureID = &metadata.m_cachedStructureID;
     int thisRegister = bytecode.m_srcDst.offset();
 
     emitLoad(thisRegister, regT3, regT2);
@@ -1051,7 +1049,7 @@
     addSlowCase(branchIfNotCell(regT3));
     addSlowCase(branchIfNotType(regT2, FinalObjectType));
     loadPtr(Address(regT2, JSCell::structureIDOffset()), regT0);
-    loadPtr(cachedStructure, regT2);
+    load32(cachedStructureID, regT2);
     addSlowCase(branchPtr(NotEqual, regT0, regT2));
 }
 

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -1695,7 +1695,7 @@
     auto bytecode = codeBlock->instructions().at(bytecodeIndex)->as<OpCatch>();
     auto& metadata = bytecode.metadata(codeBlock);
     metadata.m_buffer->forEach([&] (ValueProfileAndOperand& profile) {
-        profile.m_profile.m_buckets[0] = JSValue::encode(exec->uncheckedR(profile.m_operand).jsValue());
+        profile.m_buckets[0] = JSValue::encode(exec->uncheckedR(profile.m_operand).jsValue());
     });
 
     return nullptr;

Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -583,7 +583,7 @@
     emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);
     
     if (*ident == m_vm->propertyNames->length && shouldEmitProfiling()) {
-        Jump notArrayLengthMode = branch8(NotEqual, AbsoluteAddress(&metadata.m_mode), TrustedImm32(static_cast<uint8_t>(GetByIdMode::ArrayLength)));
+        Jump notArrayLengthMode = branch8(NotEqual, AbsoluteAddress(&metadata.m_modeMetadata.mode), TrustedImm32(static_cast<uint8_t>(GetByIdMode::ArrayLength)));
         emitArrayProfilingSiteWithCell(regT0, regT1, &metadata.m_modeMetadata.arrayLengthMode.arrayProfile);
         notArrayLengthMode.link(this);
     }

Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -580,7 +580,7 @@
     emitJumpSlowCaseIfNotJSCell(base, regT1);
 
     if (*ident == m_vm->propertyNames->length && shouldEmitProfiling()) {
-        Jump notArrayLengthMode = branch8(NotEqual, AbsoluteAddress(&metadata.m_mode), TrustedImm32(static_cast<uint8_t>(GetByIdMode::ArrayLength)));
+        Jump notArrayLengthMode = branch8(NotEqual, AbsoluteAddress(&metadata.m_modeMetadata.mode), TrustedImm32(static_cast<uint8_t>(GetByIdMode::ArrayLength)));
         emitArrayProfilingSiteWithCell(regT0, regT2, &metadata.m_modeMetadata.arrayLengthMode.arrayProfile);
         notArrayLengthMode.link(this);
     }

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -740,19 +740,12 @@
     ConcurrentJSLocker locker(codeBlock->m_lock);
 
     if (slot.isUnset()) {
-        metadata.m_mode = GetByIdMode::Unset;
-        metadata.m_modeMetadata.unsetMode.structureID = structure->id();
+        metadata.m_modeMetadata.setUnsetMode(structure);
         return;
     }
     ASSERT(slot.isValue());
 
-    metadata.m_mode = GetByIdMode::ProtoLoad;
-    metadata.m_modeMetadata.protoLoadMode.structureID = structure->id();
-    metadata.m_modeMetadata.protoLoadMode.cachedOffset = offset;
-    metadata.m_modeMetadata.protoLoadMode.cachedSlot = slot.slotBase();
-    // We know that this pointer will remain valid because it will be cleared by either a watchpoint fire or
-    // during GC when we clear the LLInt caches.
-    metadata.m_modeMetadata.protoLoadMode.cachedSlot = slot.slotBase();
+    metadata.m_modeMetadata.setProtoLoadMode(structure, offset, slot.slotBase());
 }
 
 
@@ -775,8 +768,7 @@
         && slot.isCacheable()) {
         {
             StructureID oldStructureID;
-            auto mode = metadata.m_mode;
-            switch (mode) {
+            switch (metadata.m_modeMetadata.mode) {
             case GetByIdMode::Default:
                 oldStructureID = metadata.m_modeMetadata.defaultMode.structureID;
                 break;
@@ -806,12 +798,10 @@
             ConcurrentJSLocker locker(codeBlock->m_lock);
 
             // Start out by clearing out the old cache.
-            metadata.m_mode = GetByIdMode::Default;
-            metadata.m_modeMetadata.defaultMode.structureID = 0;
-            metadata.m_modeMetadata.defaultMode.cachedOffset = 0;
+            metadata.m_modeMetadata.clearToDefaultModeWithoutCache();
 
             // Prevent the prototype cache from ever happening.
-            metadata.m_hitCountForLLIntCaching = 0;
+            metadata.m_modeMetadata.hitCountForLLIntCaching = 0;
         
             if (structure->propertyAccessesAreCacheable()
                 && !structure->needImpurePropertyWatchpoint()) {
@@ -820,10 +810,10 @@
                 metadata.m_modeMetadata.defaultMode.structureID = structure->id();
                 metadata.m_modeMetadata.defaultMode.cachedOffset = slot.cachedOffset();
             }
-        } else if (UNLIKELY(metadata.m_hitCountForLLIntCaching && (slot.isValue() || slot.isUnset()))) {
+        } else if (UNLIKELY(metadata.m_modeMetadata.hitCountForLLIntCaching && (slot.isValue() || slot.isUnset()))) {
             ASSERT(slot.slotBase() != baseValue);
 
-            if (!(--metadata.m_hitCountForLLIntCaching))
+            if (!(--metadata.m_modeMetadata.hitCountForLLIntCaching))
                 setupGetByIdPrototypeCache(exec, vm, pc, metadata, baseCell, slot, ident);
         }
     } else if (!LLINT_ALWAYS_ACCESS_SLOW
@@ -830,12 +820,8 @@
         && isJSArray(baseValue)
         && ident == vm.propertyNames->length) {
         ConcurrentJSLocker locker(codeBlock->m_lock);
-        metadata.m_mode = GetByIdMode::ArrayLength;
-        new (&metadata.m_modeMetadata.arrayLengthMode.arrayProfile) ArrayProfile(codeBlock->bytecodeOffset(pc));
+        metadata.m_modeMetadata.setArrayLengthMode();
         metadata.m_modeMetadata.arrayLengthMode.arrayProfile.observeStructure(baseValue.asCell()->structure(vm));
-
-        // Prevent the prototype cache from ever happening.
-        metadata.m_hitCountForLLIntCaching = 0;
     }
 
     LLINT_PROFILE_VALUE(result);
@@ -1503,12 +1489,7 @@
                 CodeBlock* callerCodeBlock = exec->codeBlock();
 
                 ConcurrentJSLocker locker(callerCodeBlock->m_lock);
-
-                if (callLinkInfo->isOnList())
-                    callLinkInfo->remove();
-                callLinkInfo->callee.set(vm, callerCodeBlock, internalFunction);
-                callLinkInfo->lastSeenCallee.set(vm, callerCodeBlock, internalFunction);
-                callLinkInfo->machineCodeTarget = codePtr;
+                callLinkInfo->link(vm, callerCodeBlock, internalFunction, codePtr);
             }
 
             assertIsTaggedWith(codePtr.executableAddress(), JSEntryPtrTag);
@@ -1551,12 +1532,7 @@
         CodeBlock* callerCodeBlock = exec->codeBlock();
 
         ConcurrentJSLocker locker(callerCodeBlock->m_lock);
-        
-        if (callLinkInfo->isOnList())
-            callLinkInfo->remove();
-        callLinkInfo->callee.set(vm, callerCodeBlock, callee);
-        callLinkInfo->lastSeenCallee.set(vm, callerCodeBlock, callee);
-        callLinkInfo->machineCodeTarget = codePtr;
+        callLinkInfo->link(vm, callerCodeBlock, callee, codePtr);
         if (codeBlock)
             codeBlock->linkIncomingCall(exec, callLinkInfo);
     }
@@ -1929,7 +1905,7 @@
     auto bytecode = pc->as<OpCatch>();
     auto& metadata = bytecode.metadata(exec);
     metadata.m_buffer->forEach([&] (ValueProfileAndOperand& profile) {
-        profile.m_profile.m_buckets[0] = JSValue::encode(exec->uncheckedR(profile.m_operand).jsValue());
+        profile.m_buckets[0] = JSValue::encode(exec->uncheckedR(profile.m_operand).jsValue());
     });
 
     LLINT_END();

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (245657 => 245658)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2019-05-22 23:42:30 UTC (rev 245658)
@@ -745,7 +745,7 @@
     loadi PayloadOffset[cfr, t0, 8], t0
     bbneq JSCell::m_type[t0], FinalObjectType, .opToThisSlow
     metadata(t2, t3)
-    loadp OpToThis::Metadata::m_cachedStructure[t2], t2
+    loadi OpToThis::Metadata::m_cachedStructureID[t2], t2
     bineq JSCell::m_structureID[t0], t2, .opToThisSlow
     dispatch()
 
@@ -1344,7 +1344,7 @@
 
 llintOpWithMetadata(op_get_by_id, OpGetById, macro (size, get, dispatch, metadata, return)
     metadata(t5, t0)
-    loadb OpGetById::Metadata::m_mode[t5], t1
+    loadb OpGetById::Metadata::m_modeMetadata.mode[t5], t1
     get(m_base, t0)
 
 .opGetByIdProtoLoad:
@@ -1823,7 +1823,7 @@
     bineq ThisArgumentOffset + TagOffset[cfr, t3, 8], CellTag, .done
     loadi ThisArgumentOffset + PayloadOffset[cfr, t3, 8], t0
     loadi JSCell::m_structureID[t0], t0
-    storei t0, %opcodeStruct%::Metadata::m_arrayProfile.m_lastSeenStructureID[t5]
+    storei t0, %opcodeStruct%::Metadata::m_callLinkInfo.m_arrayProfile.m_lastSeenStructureID[t5]
 .done:
 end
 
@@ -1836,7 +1836,7 @@
         end, metadata)
 
         get(m_callee, t0)
-        loadp %opcodeStruct%::Metadata::m_callLinkInfo.callee[t5], t2
+        loadp %opcodeStruct%::Metadata::m_callLinkInfo.m_calleeOrLastSeenCalleeWithLinkBit[t5], t2
         loadConstantOrVariablePayload(size, t0, CellTag, t3, .opCallSlow)
         bineq t3, t2, .opCallSlow
         getu(size, opcodeStruct, m_argv, t3)
@@ -1849,8 +1849,8 @@
         storei t2, ArgumentCount + PayloadOffset[t3]
         storei CellTag, Callee + TagOffset[t3]
         move t3, sp
-        prepareCall(%opcodeStruct%::Metadata::m_callLinkInfo.machineCodeTarget[t5], t2, t3, t4, JSEntryPtrTag)
-        callTargetFunction(size, opcodeStruct, dispatch, %opcodeStruct%::Metadata::m_callLinkInfo.machineCodeTarget[t5], JSEntryPtrTag)
+        prepareCall(%opcodeStruct%::Metadata::m_callLinkInfo.m_machineCodeTarget[t5], t2, t3, t4, JSEntryPtrTag)
+        callTargetFunction(size, opcodeStruct, dispatch, %opcodeStruct%::Metadata::m_callLinkInfo.m_machineCodeTarget[t5], JSEntryPtrTag)
 
     .opCallSlow:
         slowPathForCall(size, opcodeStruct, dispatch, slowPath, prepareCall)

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (245657 => 245658)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2019-05-22 23:42:30 UTC (rev 245658)
@@ -701,10 +701,10 @@
     loadq [cfr, t0, 8], t0
     btqnz t0, tagMask, .opToThisSlow
     bbneq JSCell::m_type[t0], FinalObjectType, .opToThisSlow
-    loadStructureWithScratch(t0, t1, t2, t3)
+    loadi JSCell::m_structureID[t0], t1
     metadata(t2, t3)
-    loadp OpToThis::Metadata::m_cachedStructure[t2], t2
-    bpneq t1, t2, .opToThisSlow
+    loadi OpToThis::Metadata::m_cachedStructureID[t2], t2
+    bineq t1, t2, .opToThisSlow
     dispatch()
 
 .opToThisSlow:
@@ -1288,7 +1288,7 @@
 
 llintOpWithMetadata(op_get_by_id, OpGetById, macro (size, get, dispatch, metadata, return)
     metadata(t2, t1)
-    loadb OpGetById::Metadata::m_mode[t2], t1
+    loadb OpGetById::Metadata::m_modeMetadata.mode[t2], t1
     get(m_base, t0)
     loadConstantOrVariableCell(size, t0, t3, .opGetByIdSlow)
 
@@ -1918,7 +1918,7 @@
     loadq ThisArgumentOffset[cfr, t3, 8], t0
     btqnz t0, tagMask, .done
     loadi JSCell::m_structureID[t0], t3
-    storei t3, %opcodeStruct%::Metadata::m_arrayProfile.m_lastSeenStructureID[t5]
+    storei t3, %opcodeStruct%::Metadata::m_callLinkInfo.m_arrayProfile.m_lastSeenStructureID[t5]
 .done:
 end
 
@@ -1931,7 +1931,7 @@
         end, metadata)
 
         get(m_callee, t0)
-        loadp %opcodeStruct%::Metadata::m_callLinkInfo.callee[t5], t2
+        loadp %opcodeStruct%::Metadata::m_callLinkInfo.m_calleeOrLastSeenCalleeWithLinkBit[t5], t2
         loadConstantOrVariable(size, t0, t3)
         bqneq t3, t2, .opCallSlow
         getu(size, opcodeStruct, m_argv, t3)
@@ -1943,8 +1943,8 @@
         storei PC, ArgumentCount + TagOffset[cfr]
         storei t2, ArgumentCount + PayloadOffset[t3]
         move t3, sp
-        prepareCall(%opcodeStruct%::Metadata::m_callLinkInfo.machineCodeTarget[t5], t2, t3, t4, JSEntryPtrTag)
-        callTargetFunction(size, opcodeStruct, dispatch, %opcodeStruct%::Metadata::m_callLinkInfo.machineCodeTarget[t5], JSEntryPtrTag)
+        prepareCall(%opcodeStruct%::Metadata::m_callLinkInfo.m_machineCodeTarget[t5], t2, t3, t4, JSEntryPtrTag)
+        callTargetFunction(size, opcodeStruct, dispatch, %opcodeStruct%::Metadata::m_callLinkInfo.m_machineCodeTarget[t5], JSEntryPtrTag)
 
     .opCallSlow:
         slowPathForCall(size, opcodeStruct, dispatch, slowPath, prepareCall)

Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -242,7 +242,7 @@
             cachedCallee.setWithoutWriteBarrier(JSCell::seenMultipleCalleeObjects());
 
         size_t inlineCapacity = bytecode.m_inlineCapacity;
-        ObjectAllocationProfile* allocationProfile = constructor->ensureRareDataAndAllocationProfile(exec, inlineCapacity)->objectAllocationProfile();
+        ObjectAllocationProfileWithPrototype* allocationProfile = constructor->ensureRareDataAndAllocationProfile(exec, inlineCapacity)->objectAllocationProfile();
         throwScope.releaseAssertNoException();
         Structure* structure = allocationProfile->structure();
         result = constructEmptyObject(exec, structure);
@@ -272,16 +272,17 @@
     auto& metadata = bytecode.metadata(exec);
     JSValue v1 = GET(bytecode.m_srcDst).jsValue();
     if (v1.isCell()) {
-        Structure* myStructure = v1.asCell()->structure(vm);
-        Structure* otherStructure = metadata.m_cachedStructure.get();
-        if (myStructure != otherStructure) {
-            if (otherStructure)
+        StructureID myStructureID = v1.asCell()->structureID();
+        StructureID otherStructureID = metadata.m_cachedStructureID;
+        if (myStructureID != otherStructureID) {
+            if (otherStructureID)
                 metadata.m_toThisStatus = ToThisConflicted;
-            metadata.m_cachedStructure.set(vm, exec->codeBlock(), myStructure);
+            metadata.m_cachedStructureID = myStructureID;
+            vm.heap.writeBarrier(exec->codeBlock(), vm.getStructure(myStructureID));
         }
     } else {
         metadata.m_toThisStatus = ToThisConflicted;
-        metadata.m_cachedStructure.clear();
+        metadata.m_cachedStructureID = 0;
     }
     // Note: We only need to do this value profiling here on the slow path. The fast path
     // just returns the input to to_this if the structure check succeeds. If the structure

Modified: trunk/Source/_javascript_Core/runtime/FunctionRareData.h (245657 => 245658)


--- trunk/Source/_javascript_Core/runtime/FunctionRareData.h	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/runtime/FunctionRareData.h	2019-05-22 23:42:30 UTC (rev 245658)
@@ -66,7 +66,7 @@
         return OBJECT_OFFSETOF(FunctionRareData, m_objectAllocationProfile);
     }
 
-    ObjectAllocationProfile* objectAllocationProfile()
+    ObjectAllocationProfileWithPrototype* objectAllocationProfile()
     {
         return &m_objectAllocationProfile;
     }
@@ -145,7 +145,7 @@
     //
     // We don't really care about 1) since this memory is rare and small in total. 2) is unfortunate but is
     // probably outweighed by the cost of 3).
-    ObjectAllocationProfile m_objectAllocationProfile;
+    ObjectAllocationProfileWithPrototype m_objectAllocationProfile;
     InlineWatchpointSet m_objectAllocationProfileWatchpoint;
     InternalFunctionAllocationProfile m_internalFunctionAllocationProfile;
     WriteBarrier<Structure> m_boundFunctionStructure;

Modified: trunk/Source/_javascript_Core/tools/HeapVerifier.cpp (245657 => 245658)


--- trunk/Source/_javascript_Core/tools/HeapVerifier.cpp	2019-05-22 23:12:07 UTC (rev 245657)
+++ trunk/Source/_javascript_Core/tools/HeapVerifier.cpp	2019-05-22 23:42:30 UTC (rev 245658)
@@ -330,7 +330,7 @@
         CodeBlock* codeBlock = jsDynamicCast<CodeBlock*>(vm, cell);
         if (UNLIKELY(codeBlock)) {
             bool success = true;
-            codeBlock->forEachValueProfile([&](ValueProfile& valueProfile) {
+            codeBlock->forEachValueProfile([&](ValueProfile& valueProfile, bool) {
                 for (unsigned i = 0; i < ValueProfile::totalNumberOfBuckets; ++i) {
                     JSValue value = JSValue::decode(valueProfile.m_buckets[i]);
                     if (!value)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to