[JSC] Lazily create sentinel Map and Set buckets
authorysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 25 Feb 2019 02:17:35 +0000 (02:17 +0000)
committerysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 25 Feb 2019 02:17:35 +0000 (02:17 +0000)
https://bugs.webkit.org/show_bug.cgi?id=194975

Reviewed by Saam Barati.

If VM::canUseJIT() returns false, we can lazily initialize sentinel Map and Set buckets.
This patch adds getters to VM which lazily allocate these buckets. We eagerly initialize
them if VM::canUseJIT() returns true since they can be touched from DFG and FTL.

* bytecode/BytecodeIntrinsicRegistry.cpp:
(JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
(JSC::BytecodeIntrinsicRegistry::sentinelMapBucketValue):
(JSC::BytecodeIntrinsicRegistry::sentinelSetBucketValue):
* bytecode/BytecodeIntrinsicRegistry.h:
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
* dfg/DFGOperations.cpp:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileGetMapBucketNext):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucket):
(JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucketNext):
* runtime/MapConstructor.cpp:
(JSC::mapPrivateFuncMapBucketNext):
* runtime/SetConstructor.cpp:
(JSC::setPrivateFuncSetBucketNext):
* runtime/VM.cpp:
(JSC::VM::VM):
(JSC::VM::sentinelSetBucketSlow):
(JSC::VM::sentinelMapBucketSlow):
* runtime/VM.h:
(JSC::VM::sentinelSetBucket):
(JSC::VM::sentinelMapBucket):

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

12 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp
Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/runtime/MapConstructor.cpp
Source/JavaScriptCore/runtime/SetConstructor.cpp
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h

index 79d245f..2a514c0 100644 (file)
@@ -1,3 +1,41 @@
+2019-02-24  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] Lazily create sentinel Map and Set buckets
+        https://bugs.webkit.org/show_bug.cgi?id=194975
+
+        Reviewed by Saam Barati.
+
+        If VM::canUseJIT() returns false, we can lazily initialize sentinel Map and Set buckets.
+        This patch adds getters to VM which lazily allocate these buckets. We eagerly initialize
+        them if VM::canUseJIT() returns true since they can be touched from DFG and FTL.
+
+        * bytecode/BytecodeIntrinsicRegistry.cpp:
+        (JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
+        (JSC::BytecodeIntrinsicRegistry::sentinelMapBucketValue):
+        (JSC::BytecodeIntrinsicRegistry::sentinelSetBucketValue):
+        * bytecode/BytecodeIntrinsicRegistry.h:
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileGetMapBucketNext):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucket):
+        (JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucketNext):
+        * runtime/MapConstructor.cpp:
+        (JSC::mapPrivateFuncMapBucketNext):
+        * runtime/SetConstructor.cpp:
+        (JSC::setPrivateFuncSetBucketNext):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        (JSC::VM::sentinelSetBucketSlow):
+        (JSC::VM::sentinelMapBucketSlow):
+        * runtime/VM.h:
+        (JSC::VM::sentinelSetBucket):
+        (JSC::VM::sentinelMapBucket):
+
 2019-02-20  Darin Adler  <darin@apple.com>
 
         Finish removing String::format
 2019-02-20  Darin Adler  <darin@apple.com>
 
         Finish removing String::format
index 329ffe8..d1ef009 100644 (file)
@@ -69,8 +69,6 @@ BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry(VM& vm)
     m_promiseStatePending.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Pending)));
     m_promiseStateFulfilled.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Fulfilled)));
     m_promiseStateRejected.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Rejected)));
     m_promiseStatePending.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Pending)));
     m_promiseStateFulfilled.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Fulfilled)));
     m_promiseStateRejected.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Rejected)));
-    m_sentinelMapBucket.set(m_vm, m_vm.sentinelMapBucket.get());
-    m_sentinelSetBucket.set(m_vm, m_vm.sentinelSetBucket.get());
     m_GeneratorResumeModeNormal.set(m_vm, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode)));
     m_GeneratorResumeModeThrow.set(m_vm, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ThrowMode)));
     m_GeneratorResumeModeReturn.set(m_vm, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ReturnMode)));
     m_GeneratorResumeModeNormal.set(m_vm, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode)));
     m_GeneratorResumeModeThrow.set(m_vm, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ThrowMode)));
     m_GeneratorResumeModeReturn.set(m_vm, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ReturnMode)));
@@ -101,8 +99,18 @@ BytecodeIntrinsicNode::EmitterType BytecodeIntrinsicRegistry::lookup(const Ident
     { \
         return m_##name.get(); \
     }
     { \
         return m_##name.get(); \
     }
-    JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS)
+    JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_SIMPLE_EACH_NAME(JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS)
 #undef JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS
 
 #undef JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS
 
+JSValue BytecodeIntrinsicRegistry::sentinelMapBucketValue(BytecodeGenerator& generator)
+{
+    return generator.vm()->sentinelMapBucket();
+}
+
+JSValue BytecodeIntrinsicRegistry::sentinelSetBucketValue(BytecodeGenerator& generator)
+{
+    return generator.vm()->sentinelSetBucket();
+}
+
 } // namespace JSC
 
 } // namespace JSC
 
index e97bd95..42f8e12 100644 (file)
@@ -66,6 +66,10 @@ class Identifier;
     macro(defineEnumerableWritableConfigurableDataProperty) \
 
 #define JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(macro) \
     macro(defineEnumerableWritableConfigurableDataProperty) \
 
 #define JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(macro) \
+    JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_SIMPLE_EACH_NAME(macro) \
+    JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_CUSTOM_EACH_NAME(macro) \
+
+#define JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_SIMPLE_EACH_NAME(macro) \
     macro(undefined) \
     macro(Infinity) \
     macro(iterationKindKey) \
     macro(undefined) \
     macro(Infinity) \
     macro(iterationKindKey) \
@@ -85,8 +89,6 @@ class Identifier;
     macro(promiseStatePending) \
     macro(promiseStateFulfilled) \
     macro(promiseStateRejected) \
     macro(promiseStatePending) \
     macro(promiseStateFulfilled) \
     macro(promiseStateRejected) \
-    macro(sentinelMapBucket) \
-    macro(sentinelSetBucket) \
     macro(GeneratorResumeModeNormal) \
     macro(GeneratorResumeModeThrow) \
     macro(GeneratorResumeModeReturn) \
     macro(GeneratorResumeModeNormal) \
     macro(GeneratorResumeModeThrow) \
     macro(GeneratorResumeModeReturn) \
@@ -101,6 +103,10 @@ class Identifier;
     macro(AsyncGeneratorSuspendReasonAwait) \
     macro(AsyncGeneratorSuspendReasonNone) \
 
     macro(AsyncGeneratorSuspendReasonAwait) \
     macro(AsyncGeneratorSuspendReasonNone) \
 
+#define JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_CUSTOM_EACH_NAME(macro) \
+    macro(sentinelMapBucket) \
+    macro(sentinelSetBucket) \
+
 class BytecodeIntrinsicRegistry {
     WTF_MAKE_FAST_ALLOCATED;
     WTF_MAKE_NONCOPYABLE(BytecodeIntrinsicRegistry);
 class BytecodeIntrinsicRegistry {
     WTF_MAKE_FAST_ALLOCATED;
     WTF_MAKE_NONCOPYABLE(BytecodeIntrinsicRegistry);
@@ -120,7 +126,7 @@ private:
     HashMap<RefPtr<UniquedStringImpl>, EmitterType, IdentifierRepHash> m_bytecodeIntrinsicMap;
 
 #define JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS(name) Strong<Unknown> m_##name;
     HashMap<RefPtr<UniquedStringImpl>, EmitterType, IdentifierRepHash> m_bytecodeIntrinsicMap;
 
 #define JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS(name) Strong<Unknown> m_##name;
-    JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS)
+    JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_SIMPLE_EACH_NAME(JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS)
 #undef JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS
 };
 
 #undef JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS
 };
 
index 010cc39..69bf14a 100644 (file)
@@ -2929,9 +2929,9 @@ bool ByteCodeParser::handleIntrinsicCall(Node* callee, VirtualRegister result, I
             Node* bucket = addToGraph(GetMapBucket, OpInfo(0), Edge(mapOrSet, useKind), Edge(normalizedKey), Edge(hash));
             JSCell* sentinel = nullptr;
             if (intrinsic == JSMapHasIntrinsic)
             Node* bucket = addToGraph(GetMapBucket, OpInfo(0), Edge(mapOrSet, useKind), Edge(normalizedKey), Edge(hash));
             JSCell* sentinel = nullptr;
             if (intrinsic == JSMapHasIntrinsic)
-                sentinel = m_vm->sentinelMapBucket.get();
+                sentinel = m_vm->sentinelMapBucket();
             else
             else
-                sentinel = m_vm->sentinelSetBucket.get();
+                sentinel = m_vm->sentinelSetBucket();
 
             FrozenValue* frozenPointer = m_graph.freeze(sentinel);
             Node* invertedResult = addToGraph(CompareEqPtr, OpInfo(frozenPointer), bucket);
 
             FrozenValue* frozenPointer = m_graph.freeze(sentinel);
             Node* invertedResult = addToGraph(CompareEqPtr, OpInfo(frozenPointer), bucket);
index 6a57826..029b091 100644 (file)
@@ -2892,7 +2892,7 @@ JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState* exec, JSCell* map, Enc
     NativeCallFrameTracer tracer(&vm, exec);
     JSMap::BucketType** bucket = jsCast<JSMap*>(map)->findBucket(exec, JSValue::decode(key), hash);
     if (!bucket)
     NativeCallFrameTracer tracer(&vm, exec);
     JSMap::BucketType** bucket = jsCast<JSMap*>(map)->findBucket(exec, JSValue::decode(key), hash);
     if (!bucket)
-        return vm.sentinelMapBucket.get();
+        return vm.sentinelMapBucket();
     return *bucket;
 }
 
     return *bucket;
 }
 
@@ -2902,7 +2902,7 @@ JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState* exec, JSCell* map, Enc
     NativeCallFrameTracer tracer(&vm, exec);
     JSSet::BucketType** bucket = jsCast<JSSet*>(map)->findBucket(exec, JSValue::decode(key), hash);
     if (!bucket)
     NativeCallFrameTracer tracer(&vm, exec);
     JSSet::BucketType** bucket = jsCast<JSSet*>(map)->findBucket(exec, JSValue::decode(key), hash);
     if (!bucket)
-        return vm.sentinelSetBucket.get();
+        return vm.sentinelSetBucket();
     return *bucket;
 }
 
     return *bucket;
 }
 
@@ -2912,7 +2912,7 @@ JSCell* JIT_OPERATION operationSetAdd(ExecState* exec, JSCell* set, EncodedJSVal
     NativeCallFrameTracer tracer(&vm, exec);
     auto* bucket = jsCast<JSSet*>(set)->addNormalized(exec, JSValue::decode(key), JSValue(), hash);
     if (!bucket)
     NativeCallFrameTracer tracer(&vm, exec);
     auto* bucket = jsCast<JSSet*>(set)->addNormalized(exec, JSValue::decode(key), JSValue(), hash);
     if (!bucket)
-        return vm.sentinelSetBucket.get();
+        return vm.sentinelSetBucket();
     return bucket;
 }
 
     return bucket;
 }
 
@@ -2922,7 +2922,7 @@ JSCell* JIT_OPERATION operationMapSet(ExecState* exec, JSCell* map, EncodedJSVal
     NativeCallFrameTracer tracer(&vm, exec);
     auto* bucket = jsCast<JSMap*>(map)->addNormalized(exec, JSValue::decode(key), JSValue::decode(value), hash);
     if (!bucket)
     NativeCallFrameTracer tracer(&vm, exec);
     auto* bucket = jsCast<JSMap*>(map)->addNormalized(exec, JSValue::decode(key), JSValue::decode(value), hash);
     if (!bucket)
-        return vm.sentinelMapBucket.get();
+        return vm.sentinelMapBucket();
     return bucket;
 }
 
     return bucket;
 }
 
index 2911288..9e79a5a 100644 (file)
@@ -11792,10 +11792,10 @@ void SpeculativeJIT::compileGetMapBucketNext(Node* node)
     notBucket.link(&m_jit);
     JSCell* sentinel = nullptr;
     if (node->bucketOwnerType() == BucketOwnerType::Map)
     notBucket.link(&m_jit);
     JSCell* sentinel = nullptr;
     if (node->bucketOwnerType() == BucketOwnerType::Map)
-        sentinel = m_jit.vm()->sentinelMapBucket.get();
+        sentinel = m_jit.vm()->sentinelMapBucket();
     else {
         ASSERT(node->bucketOwnerType() == BucketOwnerType::Set);
     else {
         ASSERT(node->bucketOwnerType() == BucketOwnerType::Set);
-        sentinel = m_jit.vm()->sentinelSetBucket.get();
+        sentinel = m_jit.vm()->sentinelSetBucket();
     }
     m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), sentinel), resultGPR);
     done.link(&m_jit);
     }
     m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), sentinel), resultGPR);
     done.link(&m_jit);
index db8df89..44b23ff 100644 (file)
@@ -4217,9 +4217,9 @@ void SpeculativeJIT::compile(Node* node)
 
         notPresentInTable.link(&m_jit);
         if (node->child1().useKind() == MapObjectUse)
 
         notPresentInTable.link(&m_jit);
         if (node->child1().useKind() == MapObjectUse)
-            m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.vm()->sentinelMapBucket.get()), resultGPR);
+            m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.vm()->sentinelMapBucket()), resultGPR);
         else
         else
-            m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.vm()->sentinelSetBucket.get()), resultGPR);
+            m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.vm()->sentinelSetBucket()), resultGPR);
         done.link(&m_jit);
         cellResult(resultGPR, node);
         break;
         done.link(&m_jit);
         cellResult(resultGPR, node);
         break;
index 87de9ba..f8a7912 100644 (file)
@@ -9744,9 +9744,9 @@ private:
         m_out.appendTo(notPresentInTable, continuation);
         ValueFromBlock notPresentResult;
         if (m_node->child1().useKind() == MapObjectUse)
         m_out.appendTo(notPresentInTable, continuation);
         ValueFromBlock notPresentResult;
         if (m_node->child1().useKind() == MapObjectUse)
-            notPresentResult = m_out.anchor(weakPointer(vm().sentinelMapBucket.get()));
+            notPresentResult = m_out.anchor(weakPointer(vm().sentinelMapBucket()));
         else if (m_node->child1().useKind() == SetObjectUse)
         else if (m_node->child1().useKind() == SetObjectUse)
-            notPresentResult = m_out.anchor(weakPointer(vm().sentinelSetBucket.get()));
+            notPresentResult = m_out.anchor(weakPointer(vm().sentinelSetBucket()));
         else
             RELEASE_ASSERT_NOT_REACHED();
         m_out.jump(continuation);
         else
             RELEASE_ASSERT_NOT_REACHED();
         m_out.jump(continuation);
@@ -9792,10 +9792,10 @@ private:
         m_out.appendTo(noBucket, hasBucket);
         ValueFromBlock noBucketResult;
         if (m_node->bucketOwnerType() == BucketOwnerType::Map)
         m_out.appendTo(noBucket, hasBucket);
         ValueFromBlock noBucketResult;
         if (m_node->bucketOwnerType() == BucketOwnerType::Map)
-            noBucketResult = m_out.anchor(weakPointer(vm().sentinelMapBucket.get()));
+            noBucketResult = m_out.anchor(weakPointer(vm().sentinelMapBucket()));
         else {
             ASSERT(m_node->bucketOwnerType() == BucketOwnerType::Set);
         else {
             ASSERT(m_node->bucketOwnerType() == BucketOwnerType::Set);
-            noBucketResult = m_out.anchor(weakPointer(vm().sentinelSetBucket.get()));
+            noBucketResult = m_out.anchor(weakPointer(vm().sentinelSetBucket()));
         }
         m_out.jump(continuation);
 
         }
         m_out.jump(continuation);
 
index 78e534b..5ee2cbf 100644 (file)
@@ -136,7 +136,7 @@ EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketNext(ExecState* exec)
             return JSValue::encode(bucket);
         bucket = bucket->next();
     }
             return JSValue::encode(bucket);
         bucket = bucket->next();
     }
-    return JSValue::encode(exec->vm().sentinelMapBucket.get());
+    return JSValue::encode(exec->vm().sentinelMapBucket());
 }
 
 EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketKey(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketKey(ExecState* exec)
index 00b7f93..f60bfce 100644 (file)
@@ -122,7 +122,7 @@ EncodedJSValue JSC_HOST_CALL setPrivateFuncSetBucketNext(ExecState* exec)
             return JSValue::encode(bucket);
         bucket = bucket->next();
     }
             return JSValue::encode(bucket);
         bucket = bucket->next();
     }
-    return JSValue::encode(exec->vm().sentinelSetBucket.get());
+    return JSValue::encode(exec->vm().sentinelSetBucket());
 }
 
 EncodedJSValue JSC_HOST_CALL setPrivateFuncSetBucketKey(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL setPrivateFuncSetBucketKey(ExecState* exec)
index 0d1efc9..d3e01cb 100644 (file)
@@ -401,8 +401,11 @@ VM::VM(VMType vmType, HeapType heapType)
     bigIntStructure.set(*this, JSBigInt::createStructure(*this, 0, jsNull()));
     executableToCodeBlockEdgeStructure.set(*this, ExecutableToCodeBlockEdge::createStructure(*this, nullptr, jsNull()));
 
     bigIntStructure.set(*this, JSBigInt::createStructure(*this, 0, jsNull()));
     executableToCodeBlockEdgeStructure.set(*this, ExecutableToCodeBlockEdge::createStructure(*this, nullptr, jsNull()));
 
-    sentinelSetBucket.set(*this, JSSet::BucketType::createSentinel(*this));
-    sentinelMapBucket.set(*this, JSMap::BucketType::createSentinel(*this));
+    // Eagerly initialize constant cells since the concurrent compiler can access them.
+    if (canUseJIT()) {
+        sentinelMapBucket();
+        sentinelSetBucket();
+    }
 
     Thread::current().setCurrentAtomicStringTable(existingEntryAtomicStringTable);
 
 
     Thread::current().setCurrentAtomicStringTable(existingEntryAtomicStringTable);
 
@@ -1284,6 +1287,23 @@ DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(moduleProgramExecutableSpace, destructi
 
 #undef DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW
 
 
 #undef DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW
 
+
+JSCell* VM::sentinelSetBucketSlow()
+{
+    ASSERT(!m_sentinelSetBucket);
+    auto* sentinel = JSSet::BucketType::createSentinel(*this);
+    m_sentinelSetBucket.set(*this, sentinel);
+    return sentinel;
+}
+
+JSCell* VM::sentinelMapBucketSlow()
+{
+    ASSERT(!m_sentinelMapBucket);
+    auto* sentinel = JSMap::BucketType::createSentinel(*this);
+    m_sentinelMapBucket.set(*this, sentinel);
+    return sentinel;
+}
+
 JSGlobalObject* VM::vmEntryGlobalObject(const CallFrame* callFrame) const
 {
     if (callFrame && callFrame->isGlobalExec()) {
 JSGlobalObject* VM::vmEntryGlobalObject(const CallFrame* callFrame) const
 {
     if (callFrame && callFrame->isGlobalExec()) {
index 5ab352f..504bf8a 100644 (file)
@@ -539,8 +539,9 @@ public:
     Strong<Structure> executableToCodeBlockEdgeStructure;
 
     Strong<JSCell> emptyPropertyNameEnumerator;
     Strong<Structure> executableToCodeBlockEdgeStructure;
 
     Strong<JSCell> emptyPropertyNameEnumerator;
-    Strong<JSCell> sentinelSetBucket;
-    Strong<JSCell> sentinelMapBucket;
+
+    Strong<JSCell> m_sentinelSetBucket;
+    Strong<JSCell> m_sentinelMapBucket;
 
     std::unique_ptr<PromiseDeferredTimer> promiseDeferredTimer;
     
 
     std::unique_ptr<PromiseDeferredTimer> promiseDeferredTimer;
     
@@ -562,6 +563,20 @@ public:
     AtomicStringTable* atomicStringTable() const { return m_atomicStringTable; }
     WTF::SymbolRegistry& symbolRegistry() { return m_symbolRegistry; }
 
     AtomicStringTable* atomicStringTable() const { return m_atomicStringTable; }
     WTF::SymbolRegistry& symbolRegistry() { return m_symbolRegistry; }
 
+    JSCell* sentinelSetBucket()
+    {
+        if (LIKELY(m_sentinelSetBucket))
+            return m_sentinelSetBucket.get();
+        return sentinelSetBucketSlow();
+    }
+
+    JSCell* sentinelMapBucket()
+    {
+        if (LIKELY(m_sentinelMapBucket))
+            return m_sentinelMapBucket.get();
+        return sentinelMapBucketSlow();
+    }
+
     WeakGCMap<SymbolImpl*, Symbol, PtrHash<SymbolImpl*>> symbolImplToSymbolMap;
 
     enum class DeletePropertyMode {
     WeakGCMap<SymbolImpl*, Symbol, PtrHash<SymbolImpl*>> symbolImplToSymbolMap;
 
     enum class DeletePropertyMode {
@@ -890,6 +905,9 @@ private:
     static VM*& sharedInstanceInternal();
     void createNativeThunk();
 
     static VM*& sharedInstanceInternal();
     void createNativeThunk();
 
+    JSCell* sentinelSetBucketSlow();
+    JSCell* sentinelMapBucketSlow();
+
     void updateStackLimits();
 
     bool isSafeToRecurse(void* stackLimit) const
     void updateStackLimits();
 
     bool isSafeToRecurse(void* stackLimit) const