diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/bytecode/Watchpoint.h | |
parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/bytecode/Watchpoint.h')
-rw-r--r-- | Source/JavaScriptCore/bytecode/Watchpoint.h | 205 |
1 files changed, 30 insertions, 175 deletions
diff --git a/Source/JavaScriptCore/bytecode/Watchpoint.h b/Source/JavaScriptCore/bytecode/Watchpoint.h index 869e908c8..8790f4e62 100644 --- a/Source/JavaScriptCore/bytecode/Watchpoint.h +++ b/Source/JavaScriptCore/bytecode/Watchpoint.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,47 +27,12 @@ #define Watchpoint_h #include <wtf/Atomics.h> -#include <wtf/FastMalloc.h> -#include <wtf/Noncopyable.h> -#include <wtf/PrintStream.h> #include <wtf/SentinelLinkedList.h> #include <wtf/ThreadSafeRefCounted.h> namespace JSC { -class FireDetail { - void* operator new(size_t) = delete; - -public: - FireDetail() - { - } - - virtual ~FireDetail() - { - } - - virtual void dump(PrintStream&) const = 0; -}; - -class StringFireDetail : public FireDetail { -public: - StringFireDetail(const char* string) - : m_string(string) - { - } - - virtual void dump(PrintStream& out) const override; - -private: - const char* m_string; -}; - -class WatchpointSet; - class Watchpoint : public BasicRawSentinelNode<Watchpoint> { - WTF_MAKE_NONCOPYABLE(Watchpoint); - WTF_MAKE_FAST_ALLOCATED; public: Watchpoint() { @@ -75,12 +40,10 @@ public: virtual ~Watchpoint(); + void fire() { fireInternal(); } + protected: - virtual void fireInternal(const FireDetail&) = 0; - -private: - friend class WatchpointSet; - void fire(const FireDetail&); + virtual void fireInternal() = 0; }; enum WatchpointState { @@ -94,14 +57,8 @@ class InlineWatchpointSet; class WatchpointSet : public ThreadSafeRefCounted<WatchpointSet> { friend class LLIntOffsetsExtractor; public: - JS_EXPORT_PRIVATE WatchpointSet(WatchpointState); - JS_EXPORT_PRIVATE ~WatchpointSet(); // Note that this will not fire any of the watchpoints; if you need to know when a WatchpointSet dies then you need a separate mechanism for this. - - // Fast way of getting the state, which only works from the main thread. - WatchpointState stateOnJSThread() const - { - return static_cast<WatchpointState>(m_state); - } + WatchpointSet(WatchpointState); + ~WatchpointSet(); // Note that this will not fire any of the watchpoints; if you need to know when a WatchpointSet dies then you need a separate mechanism for this. // It is safe to call this from another thread. It may return an old // state. Guarantees that if *first* read the state() of the thing being @@ -141,67 +98,39 @@ public: // set watchpoints that we believe will actually be fired. void startWatching() { - ASSERT(m_state != IsInvalidated); - if (m_state == IsWatched) - return; - WTF::storeStoreFence(); + ASSERT(state() != IsInvalidated); m_state = IsWatched; - WTF::storeStoreFence(); } - void fireAll(const FireDetail& detail) + void fireAll() { - if (LIKELY(m_state != IsWatched)) + if (state() != IsWatched) return; - fireAllSlow(detail); + fireAllSlow(); } - void fireAll(const char* reason) - { - if (LIKELY(m_state != IsWatched)) - return; - fireAllSlow(reason); - } - - void touch(const FireDetail& detail) + void touch() { if (state() == ClearWatchpoint) startWatching(); else - fireAll(detail); + fireAll(); } - void touch(const char* reason) - { - touch(StringFireDetail(reason)); - } - - void invalidate(const FireDetail& detail) + void invalidate() { if (state() == IsWatched) - fireAll(detail); + fireAll(); m_state = IsInvalidated; } - - void invalidate(const char* reason) - { - invalidate(StringFireDetail(reason)); - } - - bool isBeingWatched() const - { - return m_setIsNotEmpty; - } - + int8_t* addressOfState() { return &m_state; } - static ptrdiff_t offsetOfState() { return OBJECT_OFFSETOF(WatchpointSet, m_state); } int8_t* addressOfSetIsNotEmpty() { return &m_setIsNotEmpty; } - JS_EXPORT_PRIVATE void fireAllSlow(const FireDetail&); // Call only if you've checked isWatched. - JS_EXPORT_PRIVATE void fireAllSlow(const char* reason); // Ditto. + JS_EXPORT_PRIVATE void fireAllSlow(); // Call only if you've checked isWatched. private: - void fireAllWatchpoints(const FireDetail&); + void fireAllWatchpoints(); friend class InlineWatchpointSet; @@ -245,34 +174,18 @@ public: freeFat(); } - // Fast way of getting the state, which only works from the main thread. - WatchpointState stateOnJSThread() const - { - uintptr_t data = m_data; - if (isFat(data)) - return fat(data)->stateOnJSThread(); - return decodeState(data); - } - - // It is safe to call this from another thread. It may return a prior state, - // but that should be fine since you should only perform actions based on the - // state if you also add a watchpoint. - WatchpointState state() const - { - WTF::loadLoadFence(); - uintptr_t data = m_data; - WTF::loadLoadFence(); - if (isFat(data)) - return fat(data)->state(); - return decodeState(data); - } - // It is safe to call this from another thread. It may return false // even if the set actually had been invalidated, but that ought to happen // only in the case of races, and should be rare. bool hasBeenInvalidated() const { - return state() == IsInvalidated; + WTF::loadLoadFence(); + uintptr_t data = m_data; + if (isFat(data)) { + WTF::loadLoadFence(); + return fat(data)->hasBeenInvalidated(); + } + return decodeState(data) == IsInvalidated; } // Like hasBeenInvalidated(), may be called from another thread. @@ -293,10 +206,10 @@ public: m_data = encodeState(IsWatched); } - void fireAll(const FireDetail& detail) + void fireAll() { if (isFat()) { - fat()->fireAll(detail); + fat()->fireAll(); return; } if (decodeState(m_data) == ClearWatchpoint) @@ -305,77 +218,19 @@ public: WTF::storeStoreFence(); } - void invalidate(const FireDetail& detail) - { - if (isFat()) - fat()->invalidate(detail); - else - m_data = encodeState(IsInvalidated); - } - - JS_EXPORT_PRIVATE void fireAll(const char* reason); - - void touch(const FireDetail& detail) + void touch() { if (isFat()) { - fat()->touch(detail); + fat()->touch(); return; } - uintptr_t data = m_data; - if (decodeState(data) == IsInvalidated) - return; - WTF::storeStoreFence(); - if (decodeState(data) == ClearWatchpoint) + if (decodeState(m_data) == ClearWatchpoint) m_data = encodeState(IsWatched); else m_data = encodeState(IsInvalidated); WTF::storeStoreFence(); } - void touch(const char* reason) - { - touch(StringFireDetail(reason)); - } - - // Note that for any watchpoint that is visible from the DFG, it would be incorrect to write code like: - // - // if (w.isBeingWatched()) - // w.fireAll() - // - // Concurrently to this, the DFG could do: - // - // if (w.isStillValid()) - // perform optimizations; - // if (!w.isStillValid()) - // retry compilation; - // - // Note that the DFG algorithm is widespread, and sound, because fireAll() and invalidate() will leave - // the watchpoint in a !isStillValid() state. Hence, if fireAll() or invalidate() interleaved between - // the first isStillValid() check and the second one, then it would simply cause the DFG to retry - // compilation later. - // - // But, if you change some piece of state that the DFG might optimize for, but invalidate the - // watchpoint by doing: - // - // if (w.isBeingWatched()) - // w.fireAll() - // - // then the DFG would never know that you invalidated state between the two checks. - // - // There are two ways to work around this: - // - // - Call fireAll() without a isBeingWatched() check. Then, the DFG will know that the watchpoint has - // been invalidated when it does its second check. - // - // - Do not expose the watchpoint set to the DFG directly, and have your own way of validating whether - // the assumptions that the DFG thread used are still valid when the DFG code is installed. - bool isBeingWatched() const - { - if (isFat()) - return fat()->isBeingWatched(); - return false; - } - private: static const uintptr_t IsThinFlag = 1; static const uintptr_t StateMask = 6; @@ -392,7 +247,7 @@ private: static uintptr_t encodeState(WatchpointState state) { - return (static_cast<uintptr_t>(state) << StateShift) | IsThinFlag; + return (state << StateShift) | IsThinFlag; } bool isThin() const { return isThin(m_data); } |