Changeset 289515 in webkit
- Timestamp:
- Feb 9, 2022, 5:50:04 PM (3 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r289469 r289515 1 2022-02-09 Yusuke Suzuki <ysuzuki@apple.com> 2 3 Use local variable pointer for concurrently load value 4 https://bugs.webkit.org/show_bug.cgi?id=236387 5 6 Reviewed by Saam Barati. 7 8 Consistently using local pointer to load member fields in 9 10 1. WriteBarrierStructureID 11 2. JSString's fiber 12 3. Weak 13 4. WriteBarrier<SomeKindOfCell> 14 15 to encourage compilers not to load the field twice. 16 17 * heap/Weak.cpp: 18 (JSC::weakClearSlowCase): 19 * heap/Weak.h: 20 (JSC::Weak::isHashTableEmptyValue const): 21 (JSC::Weak::unsafeImpl const): 22 (JSC::Weak::clear): 23 (JSC::Weak::impl const): 24 * heap/WeakInlines.h: 25 (JSC::Weak<T>::isHashTableDeletedValue const): 26 (JSC:: const): 27 (JSC::Weak<T>::operator const): 28 (JSC::Weak<T>::get const): 29 (JSC::Weak<T>::leakImpl): 30 * runtime/JSString.cpp: 31 (JSC::JSString::dumpToStream): 32 (JSC::JSString::estimatedSize): 33 (JSC::JSString::visitChildrenImpl): 34 * runtime/JSString.h: 35 (JSC::JSString::fiberConcurrently const): 36 (JSC::JSString::is8Bit const): 37 (JSC::JSString::length const): 38 (JSC::JSString::tryGetValueImpl const): 39 (JSC::JSString::isSubstring const): 40 * runtime/WriteBarrier.h: 41 (JSC::WriteBarrierBase::get const): 42 (JSC::WriteBarrierBase::operator* const): 43 (JSC::WriteBarrierBase::operator-> const): 44 (JSC::WriteBarrierBase::operator bool const): 45 (JSC::WriteBarrierBase::operator! const): 46 (JSC::WriteBarrierBase::unvalidatedGet const): 47 (JSC::WriteBarrierBase::cell const): 48 (JSC::WriteBarrierStructureID::get const): 49 (JSC::WriteBarrierStructureID::operator* const): 50 (JSC::WriteBarrierStructureID::operator-> const): 51 (JSC::WriteBarrierStructureID::operator bool const): 52 (JSC::WriteBarrierStructureID::operator! const): 53 (JSC::WriteBarrierStructureID::unvalidatedGet const): 54 1 55 2022-02-09 Lauro Moura <lmoura@igalia.com> 2 56 -
trunk/Source/JavaScriptCore/heap/Weak.cpp
r261755 r289515 31 31 namespace JSC { 32 32 33 void weakClearSlowCase(WeakImpl* &impl)33 void weakClearSlowCase(WeakImpl* impl) 34 34 { 35 35 ASSERT(impl); 36 37 36 WeakSet::deallocate(impl); 38 impl = nullptr;39 37 } 40 38 -
trunk/Source/JavaScriptCore/heap/Weak.h
r256779 r289515 28 28 #include "JSExportMacros.h" 29 29 #include <cstddef> 30 #include <wtf/Atomics.h> 30 31 #include <wtf/HashTraits.h> 31 32 #include <wtf/Noncopyable.h> … … 38 39 39 40 // This is a free function rather than a Weak<T> member function so we can put it in Weak.cpp. 40 JS_EXPORT_PRIVATE void weakClearSlowCase(WeakImpl* &);41 JS_EXPORT_PRIVATE void weakClearSlowCase(WeakImpl*); 41 42 42 43 template<typename T> class Weak { … … 54 55 bool isHashTableDeletedValue() const; 55 56 Weak(WTF::HashTableDeletedValueType); 56 constexpr bool isHashTableEmptyValue() const { return ! m_impl; }57 constexpr bool isHashTableEmptyValue() const { return !impl(); } 57 58 58 59 Weak(Weak&&); … … 77 78 78 79 inline WeakImpl* leakImpl() WARN_UNUSED_RETURN; 79 WeakImpl* unsafeImpl() const { return m_impl; }80 WeakImpl* unsafeImpl() const { return impl(); } 80 81 void clear() 81 82 { 82 if (!m_impl) 83 auto* pointer = impl(); 84 if (!pointer) 83 85 return; 84 weakClearSlowCase(m_impl); 86 weakClearSlowCase(pointer); 87 m_impl = nullptr; 85 88 } 86 89 87 90 private: 88 91 static inline WeakImpl* hashTableDeletedValue(); 92 WeakImpl* impl() const { return m_impl; } 89 93 90 94 WeakImpl* m_impl { nullptr }; -
trunk/Source/JavaScriptCore/heap/WeakInlines.h
r261464 r289515 39 39 template<typename T> inline bool Weak<T>::isHashTableDeletedValue() const 40 40 { 41 return m_impl== hashTableDeletedValue();41 return impl() == hashTableDeletedValue(); 42 42 } 43 43 … … 71 71 template<typename T> inline T* Weak<T>::operator->() const 72 72 { 73 ASSERT(m_impl && m_impl->state() == WeakImpl::Live); 73 auto* pointer = impl(); 74 ASSERT(pointer && pointer->state() == WeakImpl::Live); 74 75 // We can't use jsCast here since we could be called in a finalizer. 75 return static_cast<T*>( m_impl->jsValue().asCell());76 return static_cast<T*>(pointer->jsValue().asCell()); 76 77 } 77 78 78 79 template<typename T> inline T& Weak<T>::operator*() const 79 80 { 80 ASSERT(m_impl && m_impl->state() == WeakImpl::Live); 81 auto* pointer = impl(); 82 ASSERT(pointer && pointer->state() == WeakImpl::Live); 81 83 // We can't use jsCast here since we could be called in a finalizer. 82 return *static_cast<T*>( m_impl->jsValue().asCell());84 return *static_cast<T*>(pointer->jsValue().asCell()); 83 85 } 84 86 85 87 template<typename T> inline T* Weak<T>::get() const 86 88 { 87 if (!m_impl || m_impl->state() != WeakImpl::Live) 89 auto* pointer = impl(); 90 if (!pointer || pointer->state() != WeakImpl::Live) 88 91 return nullptr; 89 92 // We can't use jsCast here since we could be called in a finalizer. 90 return static_cast<T*>( m_impl->jsValue().asCell());93 return static_cast<T*>(pointer->jsValue().asCell()); 91 94 } 92 95 … … 98 101 template<typename T> inline bool Weak<T>::operator!() const 99 102 { 100 return !m_impl || !m_impl->jsValue() || m_impl->state() != WeakImpl::Live; 103 auto* pointer = impl(); 104 return !pointer || !pointer->jsValue() || pointer->state() != WeakImpl::Live; 101 105 } 102 106 … … 108 112 template<typename T> inline WeakImpl* Weak<T>::leakImpl() 109 113 { 110 WeakImpl* impl = m_impl;114 auto* pointer = impl(); 111 115 m_impl = nullptr; 112 return impl;116 return pointer; 113 117 } 114 118 -
trunk/Source/JavaScriptCore/runtime/JSString.cpp
r288537 r289515 69 69 const JSString* thisObject = jsCast<const JSString*>(cell); 70 70 out.printf("<%p, %s, [%u], ", thisObject, thisObject->className(vm), thisObject->length()); 71 uintptr_t pointer = thisObject-> m_fiber;71 uintptr_t pointer = thisObject->fiberConcurrently(); 72 72 if (pointer & isRopeInPointer) { 73 73 if (pointer & JSRopeString::isSubstringInPointer) … … 104 104 { 105 105 JSString* thisObject = asString(cell); 106 uintptr_t pointer = thisObject-> m_fiber;106 uintptr_t pointer = thisObject->fiberConcurrently(); 107 107 if (pointer & isRopeInPointer) 108 108 return Base::estimatedSize(cell, vm); … … 117 117 Base::visitChildren(thisObject, visitor); 118 118 119 uintptr_t pointer = thisObject-> m_fiber;119 uintptr_t pointer = thisObject->fiberConcurrently(); 120 120 if (pointer & isRopeInPointer) { 121 121 if (pointer & JSRopeString::isSubstringInPointer) { -
trunk/Source/JavaScriptCore/runtime/JSString.h
r289359 r289515 237 237 JS_EXPORT_PRIVATE bool equalSlowCase(JSGlobalObject*, JSString* other) const; 238 238 bool isSubstring() const; 239 240 uintptr_t fiberConcurrently() const { return m_fiber; } 239 241 240 242 mutable uintptr_t m_fiber; … … 696 698 ALWAYS_INLINE bool JSString::is8Bit() const 697 699 { 698 uintptr_t pointer = m_fiber;700 uintptr_t pointer = fiberConcurrently(); 699 701 if (pointer & isRopeInPointer) { 700 702 // Do not load m_fiber twice. We should use the information in pointer. … … 710 712 ALWAYS_INLINE unsigned JSString::length() const 711 713 { 712 uintptr_t pointer = m_fiber;714 uintptr_t pointer = fiberConcurrently(); 713 715 if (pointer & isRopeInPointer) 714 716 return jsCast<const JSRopeString*>(this)->length(); … … 724 726 inline const StringImpl* JSString::tryGetValueImpl() const 725 727 { 726 uintptr_t pointer = m_fiber;728 uintptr_t pointer = fiberConcurrently(); 727 729 if (pointer & isRopeInPointer) 728 730 return nullptr; … … 1074 1076 inline bool JSString::isSubstring() const 1075 1077 { 1076 return m_fiber& JSRopeString::isSubstringInPointer;1078 return fiberConcurrently() & JSRopeString::isSubstringInPointer; 1077 1079 } 1078 1080 -
trunk/Source/JavaScriptCore/runtime/WriteBarrier.h
r288815 r289515 99 99 { 100 100 // Copy m_cell to a local to avoid multiple-read issues. (See <http://webkit.org/b/110854>) 101 StorageType cell = m_cell;101 StorageType cell = this->cell(); 102 102 if (cell) 103 103 validateCell(reinterpret_cast<JSCell*>(static_cast<void*>(Traits::unwrap(cell)))); … … 107 107 T* operator*() const 108 108 { 109 StorageType cell = m_cell;109 StorageType cell = this->cell(); 110 110 ASSERT(cell); 111 111 auto unwrapped = Traits::unwrap(cell); … … 116 116 T* operator->() const 117 117 { 118 StorageType cell = m_cell;118 StorageType cell = this->cell(); 119 119 ASSERT(cell); 120 120 auto unwrapped = Traits::unwrap(cell); … … 136 136 } 137 137 138 explicit operator bool() const { return !! m_cell; }139 140 bool operator!() const { return ! m_cell; }138 explicit operator bool() const { return !!cell(); } 139 140 bool operator!() const { return !cell(); } 141 141 142 142 void setWithoutWriteBarrier(T* value) … … 148 148 } 149 149 150 T* unvalidatedGet() const { return Traits::unwrap( m_cell); }150 T* unvalidatedGet() const { return Traits::unwrap(cell()); } 151 151 152 152 private: 153 StorageType cell() const { return m_cell; } 154 153 155 StorageType m_cell; 154 156 }; … … 282 284 { 283 285 // Copy m_structureID to a local to avoid multiple-read issues. (See <http://webkit.org/b/110854>) 284 StructureID structureID = m_structureID;286 StructureID structureID = value(); 285 287 if (structureID) { 286 288 Structure* structure = structureID.decode(); … … 293 295 Structure* operator*() const 294 296 { 295 StructureID structureID = m_structureID;297 StructureID structureID = value(); 296 298 ASSERT(structureID); 297 299 Structure* structure = structureID.decode(); … … 302 304 Structure* operator->() const 303 305 { 304 StructureID structureID = m_structureID;306 StructureID structureID = value(); 305 307 ASSERT(structureID); 306 308 Structure* structure = structureID.decode(); … … 316 318 explicit operator bool() const 317 319 { 318 return !! m_structureID;320 return !!value(); 319 321 } 320 322 321 323 bool operator!() const 322 324 { 323 return ! m_structureID;325 return !value(); 324 326 } 325 327 … … 338 340 Structure* unvalidatedGet() const 339 341 { 340 StructureID structureID = m_structureID;342 StructureID structureID = value(); 341 343 if (structureID) 342 344 return structureID.decode();
Note:
See TracChangeset
for help on using the changeset viewer.