Changeset 275969 in webkit
- Timestamp:
- Apr 14, 2021, 2:50:30 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r275965 r275969 1 2021-04-14 Mark Lam <mark.lam@apple.com> 2 3 Defer TerminationExceptions when evaluating ASSERT in HashMapIml::addNormalized(). 4 https://bugs.webkit.org/show_bug.cgi?id=224565 5 rdar://76645980 6 7 Reviewed by Yusuke Suzuki. 8 9 * stress/suppress-TerrminationException-in-ASSERT-in-HashMapImpl-addNormalized.js: Added. 10 1 11 2021-04-14 Guillaume Emont <guijemont@igalia.com> 2 12 -
trunk/Source/JavaScriptCore/ChangeLog
r275924 r275969 1 2021-04-14 Mark Lam <mark.lam@apple.com> 2 3 Defer TerminationExceptions when evaluating ASSERT in HashMapIml::addNormalized(). 4 https://bugs.webkit.org/show_bug.cgi?id=224565 5 rdar://76645980 6 7 Reviewed by Yusuke Suzuki. 8 9 HashMapImpl::addNormalized() has an ASSERT that calls jsMapHash(), which can 10 potentially throw exceptions. As a result, it has a RETURN_IF_EXCEPTION which 11 provides an opportunity to handle traps and throw a TerminationException. This 12 in turn causes the ASSERT to fail. 13 14 To fix this, we do: 15 16 1. Introduce VMTraps::DeferAction, which gives us DeferForAWhile and DeferUntilEndOfScope. 17 18 2. Templatize the DeferTermination RAII object on VMTraps::DeferAction. 19 Introduce DeferTerrminationForAWhile, which is DeferTermination<VMTraps::DeferAction::DeferForAWhile>. 20 DeferForAWhile means that the deferScope will not throw the TerminationException 21 on exit. Instead, it will re-set the NeedTermination bit in the traps, and let 22 the next trap check handle it. 23 24 3. Introduce DEFER_TERMINATION_AND_ASSERT_WITH_MESSAGE (and friends) which creates 25 a DeferTerrminationForAWhile scope before doing an ASSERT_WITH_MESSAGE. 26 27 4. Use DEFER_TERMINATION_AND_ASSERT_WITH_MESSAGE instead in HashMapImpl::addNormalized(). 28 29 * runtime/DeferTermination.h: 30 (JSC::DeferTermination::DeferTermination): 31 (JSC::DeferTermination::~DeferTermination): 32 * runtime/ExceptionHelpers.h: 33 * runtime/HashMapImpl.h: 34 (JSC::HashMapImpl::addNormalized): 35 * runtime/VMTraps.cpp: 36 (JSC::VMTraps::deferTermination): 37 (JSC::VMTraps::undoDeferTermination): 38 * runtime/VMTraps.h: 39 1 40 2021-04-13 Mark Lam <mark.lam@apple.com> 2 41 -
trunk/Source/JavaScriptCore/runtime/DeferTermination.h
r275797 r275969 32 32 namespace JSC { 33 33 34 template<VMTraps::DeferAction deferAction = VMTraps::DeferAction::DeferUntilEndOfScope> 34 35 class DeferTermination { 35 36 WTF_MAKE_NONCOPYABLE(DeferTermination); … … 39 40 : m_vm(vm) 40 41 { 41 m_vm.traps().deferTermination( );42 m_vm.traps().deferTermination(deferAction); 42 43 } 43 44 44 45 ~DeferTermination() 45 46 { 46 m_vm.traps().undoDeferTermination( );47 m_vm.traps().undoDeferTermination(deferAction); 47 48 } 48 49 … … 51 52 }; 52 53 54 using DeferTerminationForAWhile = DeferTermination<VMTraps::DeferAction::DeferForAWhile>; 55 53 56 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/ExceptionHelpers.h
r275648 r275969 29 29 #pragma once 30 30 31 #include "DeferTermination.h" 31 32 #include "ErrorInstance.h" 32 33 #include "Exception.h" … … 61 62 JS_EXPORT_PRIVATE Exception* throwStackOverflowError(JSGlobalObject*, ThrowScope&); 62 63 64 #if ASSERT_ENABLED 65 66 #define DEFER_TERMINATION_AND_ASSERT(vm, assertion, ...) do { \ 67 JSC::DeferTerminationForAWhile deferScope(vm); \ 68 ASSERT(assertion, __VA_ARGS__); \ 69 } while (false) 70 71 #define DEFER_TERMINATION_AND_ASSERT_WITH_MESSAGE(vm, assertion, ...) do { \ 72 JSC::DeferTerminationForAWhile deferScope(vm); \ 73 ASSERT_WITH_MESSAGE(assertion, __VA_ARGS__); \ 74 } while (false) 75 76 #else 77 78 #define DEFER_TERMINATION_AND_ASSERT(vm, assertion, ...) UNUSED_PARAM(vm) 79 #define DEFER_TERMINATION_AND_ASSERT_WITH_MESSAGE(vm, assertion, ...) UNUSED_PARAM(vm) 80 81 #endif // ASSERT_ENABLED 82 83 #define DEFER_TERMINATION_AND_RELEASE_ASSERT(vm, assertion, ...) do { \ 84 JSC::DeferTerminationForAWhile deferScope(vm); \ 85 RELEASE_ASSERT(assertion, __VA_ARGS__); \ 86 } while (false) 87 88 #define DEFER_TERMINATION_AND_RELEASE_ASSERT_WITH_MESSAGE(vm, assertion, ...) do { \ 89 JSC::DeferTerminationForAWhile deferScope(vm); \ 90 RELEASE_ASSERT_WITH_MESSAGE(assertion, __VA_ARGS__); \ 91 } while (false) 92 63 93 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/HashMapImpl.h
r275299 r275969 497 497 ALWAYS_INLINE HashMapBucketType* addNormalized(JSGlobalObject* globalObject, JSValue key, JSValue value, uint32_t hash) 498 498 { 499 VM& vm = getVM(globalObject); 499 500 ASSERT_WITH_MESSAGE(normalizeMapKey(key) == key, "We expect normalized values flowing into this function."); 500 ASSERT_WITH_MESSAGE(jsMapHash(globalObject, getVM(globalObject), key) == hash, "We expect hash value is what we expect.");501 502 auto* bucket = addNormalizedInternal( getVM(globalObject), key, value, hash, [&] (HashMapBucketType* bucket) {501 DEFER_TERMINATION_AND_ASSERT_WITH_MESSAGE(vm, jsMapHash(globalObject, getVM(globalObject), key) == hash, "We expect hash value is what we expect."); 502 503 auto* bucket = addNormalizedInternal(vm, key, value, hash, [&] (HashMapBucketType* bucket) { 503 504 return !isDeleted(bucket) && areKeysEqual(globalObject, key, bucket->key()); 504 505 }); -
trunk/Source/JavaScriptCore/runtime/VMTraps.cpp
r275924 r275969 416 416 } 417 417 418 void VMTraps::deferTermination( )418 void VMTraps::deferTermination(DeferAction) 419 419 { 420 420 auto locker = holdLock(*m_lock); … … 430 430 } 431 431 432 void VMTraps::undoDeferTermination( )432 void VMTraps::undoDeferTermination(DeferAction action) 433 433 { 434 434 auto locker = holdLock(*m_lock); … … 436 436 if (--m_deferTerminationCount == 0) { 437 437 VM& vm = this->vm(); 438 if (m_suspendedTerminationException || vm.terminationInProgress()) 439 vm.setException(vm.terminationException()); 438 if (m_suspendedTerminationException 439 || ((action == DeferAction::DeferUntilEndOfScope) && vm.terminationInProgress())) 440 vm.throwTerminationException(); 441 else if ((action == DeferAction::DeferForAWhile) && vm.terminationInProgress()) 442 setTrapBit(NeedTermination); // Let the next trap check handle it. 440 443 } 441 444 } -
trunk/Source/JavaScriptCore/runtime/VMTraps.h
r275797 r275969 192 192 void* trapBitsAddress() { return &m_trapBits; } 193 193 194 enum class DeferAction { 195 DeferForAWhile, 196 DeferUntilEndOfScope 197 }; 198 194 199 bool isDeferringTermination() const { return m_deferTerminationCount; } 195 JS_EXPORT_PRIVATE void deferTermination( );196 JS_EXPORT_PRIVATE void undoDeferTermination( );200 JS_EXPORT_PRIVATE void deferTermination(DeferAction); 201 JS_EXPORT_PRIVATE void undoDeferTermination(DeferAction); 197 202 198 203 void notifyGrabAllLocks()
Note:
See TracChangeset
for help on using the changeset viewer.