Skip to content

Commit

Permalink
Merge r181481 - Introduce WTF::Atomic to wrap std::atomic for a frien…
Browse files Browse the repository at this point in the history
…dlier CAS.

<https://webkit.org/b/142661>

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

Changed CodeBlock, and the DFG's crashLock to use WTF::Atomic instead of
std::atomic.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::visitAggregate):
* bytecode/CodeBlock.h:
* dfg/DFGCommon.cpp:
(JSC::DFG::startCrashing):

Source/WTF:

The CAS functions provided by std::atomic takes a reference to the expected
value and modifies it if the CAS fails.  However, in a lot of our CAS usage,
we don't want the expected value to change.  The solution to this is to
provide a WTF::Atomic struct that wraps std::atomic, and provide CAS
methods that won't alter the expected value if the CAS fails.

The method names in WTF::Atomic are chosen to be identical to those
in std::atomic so that WTF::Atomic can be a simple drop in replacement
for std::atomic.

Also changed ByteSpinLock to use WTF::Atomic instead of std::atomic.

* wtf/Atomics.h:
(WTF::Atomic::load):
(WTF::Atomic::store):
(WTF::Atomic::compare_exchange_weak):
(WTF::Atomic::compare_exchange_strong):
* wtf/ByteSpinLock.h:
(WTF::ByteSpinLock::ByteSpinLock):
(WTF::ByteSpinLock::lock):
  • Loading branch information
Mark Lam authored and carlosgcampos committed Mar 16, 2015
1 parent 4842c61 commit 5db62d1
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 19 deletions.
17 changes: 17 additions & 0 deletions Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,20 @@
2015-03-13 Mark Lam <mark.lam@apple.com>

Introduce WTF::Atomic to wrap std::atomic for a friendlier CAS.
<https://webkit.org/b/142661>

Reviewed by Filip Pizlo.

Changed CodeBlock, and the DFG's crashLock to use WTF::Atomic instead of
std::atomic.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::visitAggregate):
* bytecode/CodeBlock.h:
* dfg/DFGCommon.cpp:
(JSC::DFG::startCrashing):

2015-03-12 Mark Lam <mark.lam@apple.com>

Change the DFG crashLock to use std::atomic.
Expand Down
9 changes: 5 additions & 4 deletions Source/JavaScriptCore/bytecode/CodeBlock.cpp
Expand Up @@ -1629,7 +1629,6 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
, m_isStrictMode(other.m_isStrictMode)
, m_needsActivation(other.m_needsActivation)
, m_mayBeExecuting(false)
, m_visitAggregateHasBeenCalled(false)
, m_source(other.m_source)
, m_sourceOffset(other.m_sourceOffset)
, m_firstLineColumnOffset(other.m_firstLineColumnOffset)
Expand All @@ -1645,6 +1644,8 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
, m_capabilityLevelState(DFG::CapabilityLevelNotSet)
#endif
{
m_visitAggregateHasBeenCalled.store(false, std::memory_order_relaxed);

ASSERT(m_heap->isDeferred());
ASSERT(m_scopeRegister.isLocal());

Expand Down Expand Up @@ -1690,7 +1691,6 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
, m_isStrictMode(unlinkedCodeBlock->isStrictMode())
, m_needsActivation(unlinkedCodeBlock->hasActivationRegister() && unlinkedCodeBlock->codeType() == FunctionCode)
, m_mayBeExecuting(false)
, m_visitAggregateHasBeenCalled(false)
, m_source(sourceProvider)
, m_sourceOffset(sourceOffset)
, m_firstLineColumnOffset(firstLineColumnOffset)
Expand All @@ -1702,6 +1702,8 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
, m_capabilityLevelState(DFG::CapabilityLevelNotSet)
#endif
{
m_visitAggregateHasBeenCalled.store(false, std::memory_order_relaxed);

ASSERT(m_heap->isDeferred());
ASSERT(m_scopeRegister.isLocal());

Expand Down Expand Up @@ -2208,8 +2210,7 @@ void CodeBlock::visitAggregate(SlotVisitor& visitor)
// I may be asked to scan myself more than once, and it may even happen concurrently.
// To this end, use an atomic operation to check (and set) if I've been called already.
// Only one thread may proceed past this point - whichever one wins the atomic set race.
bool expected = false;
bool setByMe = m_visitAggregateHasBeenCalled.compare_exchange_strong(expected, true, std::memory_order_acquire);
bool setByMe = m_visitAggregateHasBeenCalled.compare_exchange_strong(false, true, std::memory_order_acquire);
if (!setByMe)
return;
#endif // ENABLE(PARALLEL_GC)
Expand Down
2 changes: 1 addition & 1 deletion Source/JavaScriptCore/bytecode/CodeBlock.h
Expand Up @@ -1056,7 +1056,7 @@ class CodeBlock : public ThreadSafeRefCounted<CodeBlock>, public UnconditionalFi
bool m_isStrictMode;
bool m_needsActivation;
bool m_mayBeExecuting;
std::atomic<bool> m_visitAggregateHasBeenCalled;
Atomic<bool> m_visitAggregateHasBeenCalled;

RefPtr<SourceProvider> m_source;
unsigned m_sourceOffset;
Expand Down
7 changes: 2 additions & 5 deletions Source/JavaScriptCore/dfg/DFGCommon.cpp
Expand Up @@ -33,15 +33,12 @@

namespace JSC { namespace DFG {

static std::atomic<unsigned> crashLock;
static Atomic<unsigned> crashLock;

void startCrashing()
{
unsigned expected = 0;
while (!crashLock.compare_exchange_weak(expected, 1, std::memory_order_acquire)) {
while (!crashLock.compare_exchange_weak(0, 1, std::memory_order_acquire))
std::this_thread::yield();
expected = 0;
}
}

bool isCrashing()
Expand Down
28 changes: 28 additions & 0 deletions Source/WTF/ChangeLog
@@ -1,3 +1,31 @@
2015-03-13 Mark Lam <mark.lam@apple.com>

Introduce WTF::Atomic to wrap std::atomic for a friendlier CAS.
<https://webkit.org/b/142661>

Reviewed by Filip Pizlo.

The CAS functions provided by std::atomic takes a reference to the expected
value and modifies it if the CAS fails. However, in a lot of our CAS usage,
we don't want the expected value to change. The solution to this is to
provide a WTF::Atomic struct that wraps std::atomic, and provide CAS
methods that won't alter the expected value if the CAS fails.

The method names in WTF::Atomic are chosen to be identical to those
in std::atomic so that WTF::Atomic can be a simple drop in replacement
for std::atomic.

Also changed ByteSpinLock to use WTF::Atomic instead of std::atomic.

* wtf/Atomics.h:
(WTF::Atomic::load):
(WTF::Atomic::store):
(WTF::Atomic::compare_exchange_weak):
(WTF::Atomic::compare_exchange_strong):
* wtf/ByteSpinLock.h:
(WTF::ByteSpinLock::ByteSpinLock):
(WTF::ByteSpinLock::lock):

2015-03-14 Michael Saboff <msaboff@apple.com>

Disable Yarr JIT for ARMv7k
Expand Down
34 changes: 33 additions & 1 deletion Source/WTF/wtf/Atomics.h
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2007, 2008, 2010, 2012, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2007-2008, 2010, 2012-2013, 2015 Apple Inc. All rights reserved.
* Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -59,6 +59,7 @@
#ifndef Atomics_h
#define Atomics_h

#include <atomic>
#include <wtf/StdLibExtras.h>

#if OS(WINDOWS)
Expand All @@ -71,6 +72,35 @@ extern "C" void _ReadWriteBarrier(void);

namespace WTF {

// Atomic wraps around std::atomic with the sole purpose of making the compare_exchange
// operations not alter the expected value. This is more in line with how we typically
// use CAS in our code.
//
// Atomic is a struct without explicitly defined constructors so that it can be
// initialized at compile time.

template<typename T>
struct Atomic {

T load(std::memory_order order) const { return value.load(order); }

void store(T desired, std::memory_order order) { value.store(desired, order); }

bool compare_exchange_weak(T expected, T desired, std::memory_order order)
{
T expectedOrActual = expected;
return value.compare_exchange_weak(expectedOrActual, desired, order);
}

bool compare_exchange_strong(T expected, T desired, std::memory_order order)
{
T expectedOrActual = expected;
return value.compare_exchange_strong(expectedOrActual, desired, order);
}

std::atomic<T> value;
};

#if OS(WINDOWS)
inline bool weakCompareAndSwap(volatile unsigned* location, unsigned expected, unsigned newValue)
{
Expand Down Expand Up @@ -345,4 +375,6 @@ inline bool weakCompareAndSwap(uint8_t* location, uint8_t expected, uint8_t newV

} // namespace WTF

using WTF::Atomic;

#endif // Atomics_h
13 changes: 5 additions & 8 deletions Source/WTF/wtf/ByteSpinLock.h
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
* Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
Expand All @@ -26,9 +26,9 @@
#ifndef ByteSpinLock_h
#define ByteSpinLock_h

#include <atomic>
#include <thread>
#include <wtf/Assertions.h>
#include <wtf/Atomics.h>
#include <wtf/Locker.h>
#include <wtf/Noncopyable.h>

Expand All @@ -38,17 +38,14 @@ class ByteSpinLock {
WTF_MAKE_NONCOPYABLE(ByteSpinLock);
public:
ByteSpinLock()
: m_lock(false)
{
m_lock.store(false, std::memory_order_relaxed);
}

void lock()
{
bool expected = false;
while (!m_lock.compare_exchange_weak(expected, true, std::memory_order_acquire)) {
while (!m_lock.compare_exchange_weak(false, true, std::memory_order_acquire))
std::this_thread::yield();
expected = false;
}
}

void unlock()
Expand All @@ -59,7 +56,7 @@ class ByteSpinLock {
bool isHeld() const { return m_lock.load(std::memory_order_acquire); }

private:
std::atomic<bool> m_lock;
Atomic<bool> m_lock;
};

typedef Locker<ByteSpinLock> ByteSpinLocker;
Expand Down

0 comments on commit 5db62d1

Please sign in to comment.