2011-09-21 23:36:35 +00:00
|
|
|
/*
|
2019-09-18 00:36:19 +00:00
|
|
|
* Copyright (C) 2011-2019 Apple Inc. All rights reserved.
|
2011-09-21 23:36:35 +00:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
|
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
|
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
|
|
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2018-10-15 14:24:49 +00:00
|
|
|
#pragma once
|
2011-09-21 23:36:35 +00:00
|
|
|
|
2012-02-02 21:49:50 +00:00
|
|
|
#include <stdio.h>
|
2011-09-21 23:36:35 +00:00
|
|
|
#include <wtf/Assertions.h>
|
2014-09-04 21:08:38 +00:00
|
|
|
#include <wtf/DataLog.h>
|
2013-10-23 18:22:09 +00:00
|
|
|
#include <wtf/HashFunctions.h>
|
|
|
|
#include <wtf/HashTraits.h>
|
2012-11-28 01:29:29 +00:00
|
|
|
#include <wtf/PrintStream.h>
|
2011-09-21 23:36:35 +00:00
|
|
|
#include <wtf/StdLibExtras.h>
|
|
|
|
|
2019-01-22 18:00:14 +00:00
|
|
|
namespace JSC {
|
|
|
|
class CachedBitVector;
|
|
|
|
}
|
|
|
|
|
2011-09-21 23:36:35 +00:00
|
|
|
namespace WTF {
|
|
|
|
|
|
|
|
// This is a space-efficient, resizeable bitvector class. In the common case it
|
|
|
|
// occupies one word, but if necessary, it will inflate this one word to point
|
|
|
|
// to a single chunk of out-of-line allocated storage to store an arbitrary number
|
|
|
|
// of bits.
|
|
|
|
//
|
|
|
|
// - The bitvector remembers the bound of how many bits can be stored, but this
|
|
|
|
// may be slightly greater (by as much as some platform-specific constant)
|
|
|
|
// than the last argument passed to ensureSize().
|
|
|
|
//
|
2011-10-11 23:50:26 +00:00
|
|
|
// - The bitvector can resize itself automatically (set, clear, get) or can be used
|
|
|
|
// in a manual mode, which is faster (quickSet, quickClear, quickGet, ensureSize).
|
|
|
|
//
|
2011-09-21 23:36:35 +00:00
|
|
|
// - Accesses ASSERT that you are within bounds.
|
|
|
|
//
|
2011-10-11 23:50:26 +00:00
|
|
|
// - Bits are automatically initialized to zero.
|
2011-09-21 23:36:35 +00:00
|
|
|
//
|
|
|
|
// On the other hand, this BitVector class may not be the fastest around, since
|
|
|
|
// it does conditionals on every get/set/clear. But it is great if you need to
|
|
|
|
// juggle a lot of variable-length BitVectors and you're worried about wasting
|
|
|
|
// space.
|
|
|
|
|
2019-08-12 20:57:15 +00:00
|
|
|
class BitVector final {
|
|
|
|
WTF_MAKE_FAST_ALLOCATED;
|
2011-09-21 23:36:35 +00:00
|
|
|
public:
|
|
|
|
BitVector()
|
|
|
|
: m_bitsOrPointer(makeInlineBits(0))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-10-11 23:50:26 +00:00
|
|
|
explicit BitVector(size_t numBits)
|
|
|
|
: m_bitsOrPointer(makeInlineBits(0))
|
|
|
|
{
|
|
|
|
ensureSize(numBits);
|
|
|
|
}
|
|
|
|
|
|
|
|
BitVector(const BitVector& other)
|
|
|
|
: m_bitsOrPointer(makeInlineBits(0))
|
|
|
|
{
|
|
|
|
(*this) = other;
|
|
|
|
}
|
|
|
|
|
2011-09-21 23:36:35 +00:00
|
|
|
|
|
|
|
~BitVector()
|
|
|
|
{
|
|
|
|
if (isInline())
|
|
|
|
return;
|
|
|
|
OutOfLineBits::destroy(outOfLineBits());
|
|
|
|
}
|
|
|
|
|
2011-10-11 23:50:26 +00:00
|
|
|
BitVector& operator=(const BitVector& other)
|
|
|
|
{
|
|
|
|
if (isInline() && other.isInline())
|
|
|
|
m_bitsOrPointer = other.m_bitsOrPointer;
|
|
|
|
else
|
|
|
|
setSlow(other);
|
|
|
|
return *this;
|
|
|
|
}
|
2011-09-21 23:36:35 +00:00
|
|
|
|
|
|
|
size_t size() const
|
|
|
|
{
|
|
|
|
if (isInline())
|
|
|
|
return maxInlineBits();
|
|
|
|
return outOfLineBits()->numBits();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ensureSize(size_t numBits)
|
|
|
|
{
|
|
|
|
if (numBits <= size())
|
|
|
|
return;
|
|
|
|
resizeOutOfLine(numBits);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Like ensureSize(), but supports reducing the size of the bitvector.
|
2012-03-23 07:14:29 +00:00
|
|
|
WTF_EXPORT_PRIVATE void resize(size_t numBits);
|
2011-09-21 23:36:35 +00:00
|
|
|
|
2012-03-23 07:14:29 +00:00
|
|
|
WTF_EXPORT_PRIVATE void clearAll();
|
2011-09-21 23:36:35 +00:00
|
|
|
|
2011-10-11 23:50:26 +00:00
|
|
|
bool quickGet(size_t bit) const
|
2011-09-21 23:36:35 +00:00
|
|
|
{
|
2013-02-11 08:06:45 +00:00
|
|
|
ASSERT_WITH_SECURITY_IMPLICATION(bit < size());
|
2011-12-01 09:05:16 +00:00
|
|
|
return !!(bits()[bit / bitsInPointer()] & (static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1))));
|
2011-09-21 23:36:35 +00:00
|
|
|
}
|
|
|
|
|
2014-08-28 19:23:02 +00:00
|
|
|
bool quickSet(size_t bit)
|
2011-09-21 23:36:35 +00:00
|
|
|
{
|
2013-02-11 08:06:45 +00:00
|
|
|
ASSERT_WITH_SECURITY_IMPLICATION(bit < size());
|
2014-08-28 19:23:02 +00:00
|
|
|
uintptr_t& word = bits()[bit / bitsInPointer()];
|
|
|
|
uintptr_t mask = static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1));
|
|
|
|
bool result = !!(word & mask);
|
|
|
|
word |= mask;
|
|
|
|
return result;
|
2011-09-21 23:36:35 +00:00
|
|
|
}
|
|
|
|
|
2014-08-28 19:23:02 +00:00
|
|
|
bool quickClear(size_t bit)
|
2011-09-21 23:36:35 +00:00
|
|
|
{
|
2013-02-11 08:06:45 +00:00
|
|
|
ASSERT_WITH_SECURITY_IMPLICATION(bit < size());
|
2014-08-28 19:23:02 +00:00
|
|
|
uintptr_t& word = bits()[bit / bitsInPointer()];
|
|
|
|
uintptr_t mask = static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1));
|
|
|
|
bool result = !!(word & mask);
|
|
|
|
word &= ~mask;
|
|
|
|
return result;
|
2011-09-21 23:36:35 +00:00
|
|
|
}
|
|
|
|
|
2014-08-28 19:23:02 +00:00
|
|
|
bool quickSet(size_t bit, bool value)
|
2011-10-11 23:50:26 +00:00
|
|
|
{
|
|
|
|
if (value)
|
2014-08-28 19:23:02 +00:00
|
|
|
return quickSet(bit);
|
|
|
|
return quickClear(bit);
|
2011-10-11 23:50:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool get(size_t bit) const
|
|
|
|
{
|
|
|
|
if (bit >= size())
|
|
|
|
return false;
|
|
|
|
return quickGet(bit);
|
|
|
|
}
|
It should be possible to run liveness over registers without also tracking Tmps
https://bugs.webkit.org/show_bug.cgi?id=152963
Reviewed by Saam Barati.
Source/JavaScriptCore:
This adds a RegLivenessAdapter so that we can run Liveness over registers. This makes it
easier to write certain kinds of phases, like ReportUsedRegisters. I anticipate writing more
code like that for handling cold function calls. It also makes code like that somewhat more
scalable, since we're no longer using HashSets.
Currently, the way we track sets of registers is with a BitVector. Normally, we use the
RegisterSet class, which wraps BitVector, so that we can add()/contains() on Reg's. But in
the liveness analysis, everything gets turned into an index. So, we want to use BitVector
directly. To do that, I needed to make the BitVector API look a bit more like a set API. I
think that this is good, because the lack of set methods (add/remove/contains) has caused
bugs in the past. This makes BitVector have methods both for set operations on bits and array
operations on bits. I think that's good, since BitVector gets used in both contexts.
* b3/B3IndexSet.h:
(JSC::B3::IndexSet::Iterable::iterator::iterator):
(JSC::B3::IndexSet::Iterable::begin):
(JSC::B3::IndexSet::dump):
* b3/air/AirInstInlines.h:
(JSC::B3::Air::ForEach<Tmp>::forEach):
(JSC::B3::Air::ForEach<Arg>::forEach):
(JSC::B3::Air::ForEach<Reg>::forEach):
(JSC::B3::Air::Inst::forEach):
* b3/air/AirLiveness.h:
(JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter):
(JSC::B3::Air::RegLivenessAdapter::maxIndex):
(JSC::B3::Air::RegLivenessAdapter::acceptsType):
(JSC::B3::Air::RegLivenessAdapter::valueToIndex):
(JSC::B3::Air::RegLivenessAdapter::indexToValue):
* b3/air/AirReportUsedRegisters.cpp:
(JSC::B3::Air::reportUsedRegisters):
* jit/Reg.h:
(JSC::Reg::next):
(JSC::Reg::index):
(JSC::Reg::maxIndex):
(JSC::Reg::isSet):
(JSC::Reg::operator bool):
* jit/RegisterSet.h:
(JSC::RegisterSet::forEach):
Source/WTF:
Add set methods (add/contains/remove) to BitVector, since it gets used as a set in a lot of
places. This also makes BitVector a drop-in replacement for HashSet<unsigned> in a lot of
places.
Also made the iterator methods of BitVector live on BitVector directly rather than behind the
thing returned from setBits(). This makes sense since that makes BitVector even more of a
drop-in for HashSet. It's not harmful since we've never added any other mode of iterating a
BitVector other than this, so it doesn't make sense to make it harder to access.
* wtf/BitVector.h:
(WTF::BitVector::get):
(WTF::BitVector::contains):
(WTF::BitVector::set):
(WTF::BitVector::add):
(WTF::BitVector::ensureSizeAndSet):
(WTF::BitVector::clear):
(WTF::BitVector::remove):
(WTF::BitVector::hash):
(WTF::BitVector::iterator::iterator):
(WTF::BitVector::iterator::operator*):
(WTF::BitVector::iterator::operator++):
(WTF::BitVector::iterator::operator==):
(WTF::BitVector::iterator::operator!=):
(WTF::BitVector::begin):
(WTF::BitVector::end):
(WTF::BitVector::bitsInPointer):
(WTF::BitVector::SetBitsIterable::SetBitsIterable): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::iterator): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator*): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator++): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator==): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator!=): Deleted.
(WTF::BitVector::SetBitsIterable::begin): Deleted.
(WTF::BitVector::SetBitsIterable::end): Deleted.
(WTF::BitVector::setBits): Deleted.
Canonical link: https://commits.webkit.org/171043@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@194834 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-01-11 00:58:34 +00:00
|
|
|
|
|
|
|
bool contains(size_t bit) const
|
|
|
|
{
|
|
|
|
return get(bit);
|
|
|
|
}
|
2011-10-11 23:50:26 +00:00
|
|
|
|
2014-08-28 19:23:02 +00:00
|
|
|
bool set(size_t bit)
|
2011-10-11 23:50:26 +00:00
|
|
|
{
|
|
|
|
ensureSize(bit + 1);
|
2014-08-28 19:23:02 +00:00
|
|
|
return quickSet(bit);
|
2011-10-11 23:50:26 +00:00
|
|
|
}
|
2012-03-26 23:59:27 +00:00
|
|
|
|
It should be possible to run liveness over registers without also tracking Tmps
https://bugs.webkit.org/show_bug.cgi?id=152963
Reviewed by Saam Barati.
Source/JavaScriptCore:
This adds a RegLivenessAdapter so that we can run Liveness over registers. This makes it
easier to write certain kinds of phases, like ReportUsedRegisters. I anticipate writing more
code like that for handling cold function calls. It also makes code like that somewhat more
scalable, since we're no longer using HashSets.
Currently, the way we track sets of registers is with a BitVector. Normally, we use the
RegisterSet class, which wraps BitVector, so that we can add()/contains() on Reg's. But in
the liveness analysis, everything gets turned into an index. So, we want to use BitVector
directly. To do that, I needed to make the BitVector API look a bit more like a set API. I
think that this is good, because the lack of set methods (add/remove/contains) has caused
bugs in the past. This makes BitVector have methods both for set operations on bits and array
operations on bits. I think that's good, since BitVector gets used in both contexts.
* b3/B3IndexSet.h:
(JSC::B3::IndexSet::Iterable::iterator::iterator):
(JSC::B3::IndexSet::Iterable::begin):
(JSC::B3::IndexSet::dump):
* b3/air/AirInstInlines.h:
(JSC::B3::Air::ForEach<Tmp>::forEach):
(JSC::B3::Air::ForEach<Arg>::forEach):
(JSC::B3::Air::ForEach<Reg>::forEach):
(JSC::B3::Air::Inst::forEach):
* b3/air/AirLiveness.h:
(JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter):
(JSC::B3::Air::RegLivenessAdapter::maxIndex):
(JSC::B3::Air::RegLivenessAdapter::acceptsType):
(JSC::B3::Air::RegLivenessAdapter::valueToIndex):
(JSC::B3::Air::RegLivenessAdapter::indexToValue):
* b3/air/AirReportUsedRegisters.cpp:
(JSC::B3::Air::reportUsedRegisters):
* jit/Reg.h:
(JSC::Reg::next):
(JSC::Reg::index):
(JSC::Reg::maxIndex):
(JSC::Reg::isSet):
(JSC::Reg::operator bool):
* jit/RegisterSet.h:
(JSC::RegisterSet::forEach):
Source/WTF:
Add set methods (add/contains/remove) to BitVector, since it gets used as a set in a lot of
places. This also makes BitVector a drop-in replacement for HashSet<unsigned> in a lot of
places.
Also made the iterator methods of BitVector live on BitVector directly rather than behind the
thing returned from setBits(). This makes sense since that makes BitVector even more of a
drop-in for HashSet. It's not harmful since we've never added any other mode of iterating a
BitVector other than this, so it doesn't make sense to make it harder to access.
* wtf/BitVector.h:
(WTF::BitVector::get):
(WTF::BitVector::contains):
(WTF::BitVector::set):
(WTF::BitVector::add):
(WTF::BitVector::ensureSizeAndSet):
(WTF::BitVector::clear):
(WTF::BitVector::remove):
(WTF::BitVector::hash):
(WTF::BitVector::iterator::iterator):
(WTF::BitVector::iterator::operator*):
(WTF::BitVector::iterator::operator++):
(WTF::BitVector::iterator::operator==):
(WTF::BitVector::iterator::operator!=):
(WTF::BitVector::begin):
(WTF::BitVector::end):
(WTF::BitVector::bitsInPointer):
(WTF::BitVector::SetBitsIterable::SetBitsIterable): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::iterator): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator*): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator++): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator==): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator!=): Deleted.
(WTF::BitVector::SetBitsIterable::begin): Deleted.
(WTF::BitVector::SetBitsIterable::end): Deleted.
(WTF::BitVector::setBits): Deleted.
Canonical link: https://commits.webkit.org/171043@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@194834 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-01-11 00:58:34 +00:00
|
|
|
// This works like the add methods of sets. Instead of returning the previous value, like set(),
|
|
|
|
// it returns whether the bit transitioned from false to true.
|
|
|
|
bool add(size_t bit)
|
|
|
|
{
|
|
|
|
return !set(bit);
|
|
|
|
}
|
|
|
|
|
2014-08-28 19:23:02 +00:00
|
|
|
bool ensureSizeAndSet(size_t bit, size_t size)
|
2012-03-26 23:59:27 +00:00
|
|
|
{
|
|
|
|
ensureSize(size);
|
2014-08-28 19:23:02 +00:00
|
|
|
return quickSet(bit);
|
2012-03-26 23:59:27 +00:00
|
|
|
}
|
|
|
|
|
2014-08-28 19:23:02 +00:00
|
|
|
bool clear(size_t bit)
|
2011-10-11 23:50:26 +00:00
|
|
|
{
|
|
|
|
if (bit >= size())
|
2014-08-28 19:23:02 +00:00
|
|
|
return false;
|
|
|
|
return quickClear(bit);
|
2011-10-11 23:50:26 +00:00
|
|
|
}
|
It should be possible to run liveness over registers without also tracking Tmps
https://bugs.webkit.org/show_bug.cgi?id=152963
Reviewed by Saam Barati.
Source/JavaScriptCore:
This adds a RegLivenessAdapter so that we can run Liveness over registers. This makes it
easier to write certain kinds of phases, like ReportUsedRegisters. I anticipate writing more
code like that for handling cold function calls. It also makes code like that somewhat more
scalable, since we're no longer using HashSets.
Currently, the way we track sets of registers is with a BitVector. Normally, we use the
RegisterSet class, which wraps BitVector, so that we can add()/contains() on Reg's. But in
the liveness analysis, everything gets turned into an index. So, we want to use BitVector
directly. To do that, I needed to make the BitVector API look a bit more like a set API. I
think that this is good, because the lack of set methods (add/remove/contains) has caused
bugs in the past. This makes BitVector have methods both for set operations on bits and array
operations on bits. I think that's good, since BitVector gets used in both contexts.
* b3/B3IndexSet.h:
(JSC::B3::IndexSet::Iterable::iterator::iterator):
(JSC::B3::IndexSet::Iterable::begin):
(JSC::B3::IndexSet::dump):
* b3/air/AirInstInlines.h:
(JSC::B3::Air::ForEach<Tmp>::forEach):
(JSC::B3::Air::ForEach<Arg>::forEach):
(JSC::B3::Air::ForEach<Reg>::forEach):
(JSC::B3::Air::Inst::forEach):
* b3/air/AirLiveness.h:
(JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter):
(JSC::B3::Air::RegLivenessAdapter::maxIndex):
(JSC::B3::Air::RegLivenessAdapter::acceptsType):
(JSC::B3::Air::RegLivenessAdapter::valueToIndex):
(JSC::B3::Air::RegLivenessAdapter::indexToValue):
* b3/air/AirReportUsedRegisters.cpp:
(JSC::B3::Air::reportUsedRegisters):
* jit/Reg.h:
(JSC::Reg::next):
(JSC::Reg::index):
(JSC::Reg::maxIndex):
(JSC::Reg::isSet):
(JSC::Reg::operator bool):
* jit/RegisterSet.h:
(JSC::RegisterSet::forEach):
Source/WTF:
Add set methods (add/contains/remove) to BitVector, since it gets used as a set in a lot of
places. This also makes BitVector a drop-in replacement for HashSet<unsigned> in a lot of
places.
Also made the iterator methods of BitVector live on BitVector directly rather than behind the
thing returned from setBits(). This makes sense since that makes BitVector even more of a
drop-in for HashSet. It's not harmful since we've never added any other mode of iterating a
BitVector other than this, so it doesn't make sense to make it harder to access.
* wtf/BitVector.h:
(WTF::BitVector::get):
(WTF::BitVector::contains):
(WTF::BitVector::set):
(WTF::BitVector::add):
(WTF::BitVector::ensureSizeAndSet):
(WTF::BitVector::clear):
(WTF::BitVector::remove):
(WTF::BitVector::hash):
(WTF::BitVector::iterator::iterator):
(WTF::BitVector::iterator::operator*):
(WTF::BitVector::iterator::operator++):
(WTF::BitVector::iterator::operator==):
(WTF::BitVector::iterator::operator!=):
(WTF::BitVector::begin):
(WTF::BitVector::end):
(WTF::BitVector::bitsInPointer):
(WTF::BitVector::SetBitsIterable::SetBitsIterable): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::iterator): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator*): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator++): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator==): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator!=): Deleted.
(WTF::BitVector::SetBitsIterable::begin): Deleted.
(WTF::BitVector::SetBitsIterable::end): Deleted.
(WTF::BitVector::setBits): Deleted.
Canonical link: https://commits.webkit.org/171043@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@194834 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-01-11 00:58:34 +00:00
|
|
|
|
|
|
|
bool remove(size_t bit)
|
|
|
|
{
|
|
|
|
return clear(bit);
|
|
|
|
}
|
2011-10-11 23:50:26 +00:00
|
|
|
|
2014-08-28 19:23:02 +00:00
|
|
|
bool set(size_t bit, bool value)
|
2011-09-21 23:36:35 +00:00
|
|
|
{
|
|
|
|
if (value)
|
2014-08-28 19:23:02 +00:00
|
|
|
return set(bit);
|
|
|
|
return clear(bit);
|
2011-09-21 23:36:35 +00:00
|
|
|
}
|
|
|
|
|
2013-10-21 04:48:29 +00:00
|
|
|
void merge(const BitVector& other)
|
|
|
|
{
|
|
|
|
if (!isInline() || !other.isInline()) {
|
|
|
|
mergeSlow(other);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_bitsOrPointer |= other.m_bitsOrPointer;
|
2013-10-23 18:22:09 +00:00
|
|
|
ASSERT(isInline());
|
2013-10-21 04:48:29 +00:00
|
|
|
}
|
|
|
|
|
Switch FTL GetById/PutById IC's over to using AnyRegCC
https://bugs.webkit.org/show_bug.cgi?id=124094
Source/JavaScriptCore:
Reviewed by Sam Weinig.
This closes the loop on inline caches (IC's) in the FTL. The goal is to have IC's
in LLVM-generated code that are just as efficient (if not more so) than what a
custom JIT could do. As in zero sources of overhead. Not a single extra instruction
or even register allocation pathology. We accomplish this by having two thingies in
LLVM. First is the llvm.experimental.patchpoint intrinsic, which is sort of an
inline machine code snippet that we can fill in with whatever we want and then
modify subsequently. But you have only two choices of how to pass values to a
patchpoint: (1) via the calling convention or (2) via the stackmap. Neither are good
for operands to an IC (like the base pointer for a GetById, for example). (1) is bad
because it results in things being pinned to certain registers a priori; a custom
JIT (like the DFG) will not pin IC operands to any registers a priori but will allow
the register allocator to do whatever it wants. (2) is bad because the operands may
be spilled or may be represented in other crazy ways. You generally want an IC to
have its operands in registers. Also, patchpoints only return values using the
calling convention, which is unfortunate since it pins the return value to a
register a priori. This is where the second thingy comes in: the AnyRegCC. This is
a special calling convention only for use with patchpoints. It means that arguments
passed "by CC" in the patchpoint can be placed in any register, and the register
that gets used is reported as part of the stackmap. It also means that the return
value (if there is one) can be placed in any register, and the stackmap will tell
you which one it was. Thus, patchpoints combined with AnyRegCC mean that you not
only get the kind of self-modifying code that you want for IC's, but you also get
all of the register allocation goodness that a custom JIT would have given you.
Except that you're getting it from LLVM and not a custom JIT. Awesome.
Even though all of the fun stuff is on the LLVM side, this patch was harder than
you'd expect.
First the obvious bits:
- IC patchpoints now use AnyRegCC instead of the C CC. (CC = calling convention.)
- FTL::fixFunctionBasedOnStackMaps() now correctly figures out which registers the
IC is supposed to use instead of assuming C CC argument registers.
And then all of the stuff that broke and that this patch fixes:
- IC sizing based on generating a dummy IC (what FTLInlineCacheSize did) is totally
bad on x86-64, where various register permutations lead to bizarre header bytes
and eclectic SIB encodings. I changed that to have magic constants, for now.
- Slow path calls didn't preserve the CC return register.
- Repatch's scratch register allocation would get totally confused if the operand
registers weren't one of the DFG-style "temp" registers. And by "totally confused"
I mean that it would crash.
- We assumed that r10 is callee-saved. It's not. That one dude's PPT about x86-64
cdecl that I found on the intertubes was not a trustworthy source of information,
apparently.
- Call repatching didn't know that the FTL does its IC slow calls via specially
generated thunks. This was particularly fun to fix: basically, now when we relink
an IC call in the FTL, we use the old call target to find the SlowPathCallKey,
which tells us everything we need to know to generate (or look up) a new thunk for
the new function we want to call.
* assembler/MacroAssemblerCodeRef.h:
(JSC::MacroAssemblerCodePtr::MacroAssemblerCodePtr):
(JSC::MacroAssemblerCodePtr::isEmptyValue):
(JSC::MacroAssemblerCodePtr::isDeletedValue):
(JSC::MacroAssemblerCodePtr::hash):
(JSC::MacroAssemblerCodePtr::emptyValue):
(JSC::MacroAssemblerCodePtr::deletedValue):
(JSC::MacroAssemblerCodePtrHash::hash):
(JSC::MacroAssemblerCodePtrHash::equal):
* assembler/MacroAssemblerX86Common.h:
* assembler/RepatchBuffer.h:
(JSC::RepatchBuffer::RepatchBuffer):
(JSC::RepatchBuffer::codeBlock):
* ftl/FTLAbbreviations.h:
(JSC::FTL::setInstructionCallingConvention):
* ftl/FTLCompile.cpp:
(JSC::FTL::fixFunctionBasedOnStackMaps):
* ftl/FTLInlineCacheSize.cpp:
(JSC::FTL::sizeOfGetById):
(JSC::FTL::sizeOfPutById):
* ftl/FTLJITFinalizer.cpp:
(JSC::FTL::JITFinalizer::finalizeFunction):
* ftl/FTLLocation.cpp:
(JSC::FTL::Location::forStackmaps):
* ftl/FTLLocation.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileGetById):
(JSC::FTL::LowerDFGToLLVM::compilePutById):
* ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::compileStub):
* ftl/FTLSlowPathCall.cpp:
* ftl/FTLSlowPathCallKey.h:
(JSC::FTL::SlowPathCallKey::withCallTarget):
* ftl/FTLStackMaps.cpp:
(JSC::FTL::StackMaps::Location::directGPR):
(JSC::FTL::StackMaps::Location::restoreInto):
* ftl/FTLStackMaps.h:
* ftl/FTLThunks.h:
(JSC::FTL::generateIfNecessary):
(JSC::FTL::keyForThunk):
(JSC::FTL::Thunks::keyForSlowPathCallThunk):
* jit/FPRInfo.h:
(JSC::FPRInfo::toIndex):
* jit/GPRInfo.h:
(JSC::GPRInfo::toIndex):
(JSC::GPRInfo::debugName):
* jit/RegisterSet.cpp:
(JSC::RegisterSet::calleeSaveRegisters):
* jit/RegisterSet.h:
(JSC::RegisterSet::filter):
* jit/Repatch.cpp:
(JSC::readCallTarget):
(JSC::repatchCall):
(JSC::repatchByIdSelfAccess):
(JSC::tryCacheGetByID):
(JSC::tryCachePutByID):
(JSC::tryBuildPutByIdList):
(JSC::resetGetByID):
(JSC::resetPutByID):
* jit/ScratchRegisterAllocator.h:
(JSC::ScratchRegisterAllocator::lock):
Source/WTF:
Reviewed by Sam Weinig.
I needed to add another set operation, namely filter(), which is an in-place set
intersection.
* wtf/BitVector.cpp:
(WTF::BitVector::filterSlow):
* wtf/BitVector.h:
(WTF::BitVector::filter):
Canonical link: https://commits.webkit.org/142336@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@159039 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2013-11-11 07:30:50 +00:00
|
|
|
void filter(const BitVector& other)
|
|
|
|
{
|
|
|
|
if (!isInline() || !other.isInline()) {
|
|
|
|
filterSlow(other);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_bitsOrPointer &= other.m_bitsOrPointer;
|
|
|
|
ASSERT(isInline());
|
|
|
|
}
|
|
|
|
|
2013-10-23 18:22:09 +00:00
|
|
|
void exclude(const BitVector& other)
|
|
|
|
{
|
|
|
|
if (!isInline() || !other.isInline()) {
|
|
|
|
excludeSlow(other);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_bitsOrPointer &= ~other.m_bitsOrPointer;
|
|
|
|
m_bitsOrPointer |= (static_cast<uintptr_t>(1) << maxInlineBits());
|
|
|
|
ASSERT(isInline());
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t bitCount() const
|
|
|
|
{
|
|
|
|
if (isInline())
|
|
|
|
return bitCount(cleanseInlineBits(m_bitsOrPointer));
|
|
|
|
return bitCountSlow();
|
|
|
|
}
|
2019-05-07 20:46:43 +00:00
|
|
|
|
|
|
|
bool isEmpty() const
|
|
|
|
{
|
|
|
|
if (isInline())
|
|
|
|
return !cleanseInlineBits(m_bitsOrPointer);
|
|
|
|
return isEmptySlow();
|
|
|
|
}
|
2013-10-23 18:22:09 +00:00
|
|
|
|
2014-09-04 21:08:38 +00:00
|
|
|
size_t findBit(size_t index, bool value) const
|
|
|
|
{
|
|
|
|
size_t result = findBitFast(index, value);
|
PerformanceTests:
Convert ASSERT_DISABLED to ASSERT_ENABLED, and fix some tests of NDEBUG that should actually test for ASSERT_ENABLED.
https://bugs.webkit.org/show_bug.cgi?id=205776
Reviewed by Saam Barati.
* JetStream2/wasm/HashSet.cpp:
* StitchMarker/wtf/Assertions.h:
* StitchMarker/wtf/DateMath.cpp:
(WTF::initializeDates):
* StitchMarker/wtf/HashTable.h:
* StitchMarker/wtf/Hasher.h:
(WTF::StringHasher::addCharacters):
* StitchMarker/wtf/NeverDestroyed.h:
(WTF::LazyNeverDestroyed::construct):
* StitchMarker/wtf/StackBounds.h:
(WTF::StackBounds::checkConsistency const):
* StitchMarker/wtf/ValueCheck.h:
* StitchMarker/wtf/Vector.h:
(WTF::minCapacity>::checkConsistency):
* StitchMarker/wtf/text/AtomicStringImpl.cpp:
* StitchMarker/wtf/text/AtomicStringImpl.h:
* StitchMarker/wtf/text/StringCommon.h:
(WTF::hasPrefixWithLettersIgnoringASCIICaseCommon):
* StitchMarker/wtf/text/StringImpl.h:
* StitchMarker/wtf/text/SymbolImpl.h:
* StitchMarker/wtf/text/UniquedStringImpl.h:
Source/JavaScriptCore:
Convert ASSERT_DISABLED to ASSERT_ENABLED, and fix some tests of NDEBUG that should actually test for ASSERT_ENABLED.
https://bugs.webkit.org/show_bug.cgi?id=205776
Reviewed by Saam Barati.
* API/tests/testapi.c:
* assembler/ARM64Assembler.h:
(JSC::ARM64Assembler::replaceWithLoad):
(JSC::ARM64Assembler::replaceWithAddressComputation):
* assembler/AssemblerBuffer.h:
(JSC::AssemblerBuffer::LocalWriter::LocalWriter):
* assembler/LinkBuffer.cpp:
(JSC::LinkBuffer::copyCompactAndLinkCode):
* assembler/ProbeStack.cpp:
(JSC::Probe::Stack::Stack):
* assembler/ProbeStack.h:
* b3/B3FoldPathConstants.cpp:
* b3/B3LowerToAir.cpp:
* b3/B3MemoryValue.cpp:
(JSC::B3::MemoryValue::MemoryValue):
* b3/B3Opcode.cpp:
* b3/B3Type.h:
* b3/B3TypeMap.h:
* b3/B3Width.h:
* b3/air/AirAllocateRegistersAndStackAndGenerateCode.cpp:
(JSC::B3::Air::GenerateAndAllocateRegisters::prepareForGeneration):
(JSC::B3::Air::GenerateAndAllocateRegisters::generate):
* b3/air/AirAllocateRegistersAndStackAndGenerateCode.h:
* b3/air/AirAllocateRegistersByGraphColoring.cpp:
* b3/air/AirArg.cpp:
* b3/air/AirArg.h:
* b3/air/AirCode.h:
* b3/air/AirEmitShuffle.cpp:
(JSC::B3::Air::emitShuffle):
* builtins/BuiltinExecutables.cpp:
(JSC::BuiltinExecutables::createExecutable):
* bytecode/AccessCase.cpp:
* bytecode/AccessCase.h:
* bytecode/CallVariant.cpp:
(JSC::variantListWithVariant):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::ensureCatchLivenessIsComputedForBytecodeIndex):
* bytecode/CodeBlockHash.cpp:
(JSC::CodeBlockHash::dump const):
* bytecode/StructureStubInfo.cpp:
* bytecode/StructureStubInfo.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::FunctionCallResolveNode::emitBytecode):
* bytecompiler/RegisterID.h:
(JSC::RegisterID::RegisterID):
(JSC::RegisterID::setIndex):
* debugger/Debugger.cpp:
(JSC::Debugger::removeBreakpoint):
* debugger/DebuggerEvalEnabler.h:
(JSC::DebuggerEvalEnabler::DebuggerEvalEnabler):
(JSC::DebuggerEvalEnabler::~DebuggerEvalEnabler):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::observeTransitions):
* dfg/DFGAbstractValue.cpp:
* dfg/DFGAbstractValue.h:
(JSC::DFG::AbstractValue::merge):
(JSC::DFG::AbstractValue::checkConsistency const):
(JSC::DFG::AbstractValue::assertIsRegistered const):
* dfg/DFGArithMode.h:
(JSC::DFG::doesOverflow):
* dfg/DFGBasicBlock.cpp:
(JSC::DFG::BasicBlock::BasicBlock):
* dfg/DFGBasicBlock.h:
(JSC::DFG::BasicBlock::didLink):
* dfg/DFGCFAPhase.cpp:
(JSC::DFG::CFAPhase::performBlockCFA):
* dfg/DFGCommon.h:
(JSC::DFG::validationEnabled):
* dfg/DFGCommonData.cpp:
(JSC::DFG::CommonData::finalizeCatchEntrypoints):
* dfg/DFGDesiredWatchpoints.h:
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGEdge.h:
(JSC::DFG::Edge::makeWord):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGJITCode.cpp:
(JSC::DFG::JITCode::finalizeOSREntrypoints):
* dfg/DFGObjectAllocationSinkingPhase.cpp:
* dfg/DFGSSAConversionPhase.cpp:
(JSC::DFG::SSAConversionPhase::run):
* dfg/DFGScoreBoard.h:
(JSC::DFG::ScoreBoard::assertClear):
* dfg/DFGSlowPathGenerator.h:
(JSC::DFG::SlowPathGenerator::generate):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileCurrentBlock):
(JSC::DFG::SpeculativeJIT::emitBinarySwitchStringRecurse):
(JSC::DFG::SpeculativeJIT::emitAllocateButterfly):
(JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):
(JSC::DFG::SpeculativeJIT::compileMakeRope):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
* dfg/DFGStructureAbstractValue.cpp:
* dfg/DFGStructureAbstractValue.h:
(JSC::DFG::StructureAbstractValue::assertIsRegistered const):
* dfg/DFGVarargsForwardingPhase.cpp:
* dfg/DFGVirtualRegisterAllocationPhase.cpp:
(JSC::DFG::VirtualRegisterAllocationPhase::run):
* ftl/FTLLink.cpp:
(JSC::FTL::link):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::callPreflight):
(JSC::FTL::DFG::LowerDFGToB3::callCheck):
(JSC::FTL::DFG::LowerDFGToB3::crash):
* ftl/FTLOperations.cpp:
(JSC::FTL::operationMaterializeObjectInOSR):
* heap/BlockDirectory.cpp:
(JSC::BlockDirectory::assertNoUnswept):
* heap/GCSegmentedArray.h:
(JSC::GCArraySegment::GCArraySegment):
* heap/GCSegmentedArrayInlines.h:
(JSC::GCSegmentedArray<T>::clear):
(JSC::GCSegmentedArray<T>::expand):
(JSC::GCSegmentedArray<T>::validatePrevious):
* heap/HandleSet.cpp:
* heap/HandleSet.h:
* heap/Heap.cpp:
(JSC::Heap::updateAllocationLimits):
* heap/Heap.h:
* heap/MarkedBlock.cpp:
* heap/MarkedBlock.h:
(JSC::MarkedBlock::assertValidCell const):
(JSC::MarkedBlock::assertMarksNotStale):
* heap/MarkedSpace.cpp:
(JSC::MarkedSpace::beginMarking):
(JSC::MarkedSpace::endMarking):
(JSC::MarkedSpace::assertNoUnswept):
* heap/PreciseAllocation.cpp:
* heap/PreciseAllocation.h:
(JSC::PreciseAllocation::assertValidCell const):
* heap/SlotVisitor.cpp:
(JSC::SlotVisitor::SlotVisitor):
(JSC::SlotVisitor::appendJSCellOrAuxiliary):
* heap/SlotVisitor.h:
* inspector/InspectorProtocolTypes.h:
(Inspector::Protocol::BindingTraits<JSON::ArrayOf<T>>::assertValueHasExpectedType):
* inspector/scripts/codegen/generate_cpp_protocol_types_implementation.py:
(CppProtocolTypesImplementationGenerator._generate_assertion_for_object_declaration):
(CppProtocolTypesImplementationGenerator):
(CppProtocolTypesImplementationGenerator._generate_assertion_for_enum):
* inspector/scripts/tests/generic/expected/type-requiring-runtime-casts.json-result:
* interpreter/FrameTracers.h:
(JSC::JITOperationPrologueCallFrameTracer::JITOperationPrologueCallFrameTracer):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::Interpreter):
* interpreter/Interpreter.h:
* jit/AssemblyHelpers.cpp:
(JSC::AssemblyHelpers::emitStoreStructureWithTypeInfo):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::prepareCallOperation):
* jit/BinarySwitch.cpp:
(JSC::BinarySwitch::BinarySwitch):
* jit/CCallHelpers.h:
(JSC::CCallHelpers::setupStubArgs):
* jit/CallFrameShuffler.cpp:
(JSC::CallFrameShuffler::emitDeltaCheck):
(JSC::CallFrameShuffler::prepareAny):
* jit/JIT.cpp:
(JSC::JIT::assertStackPointerOffset):
(JSC::JIT::compileWithoutLinking):
* jit/JITOpcodes.cpp:
(JSC::JIT::emitSlow_op_loop_hint):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_get_from_scope):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_get_from_scope):
* jit/Repatch.cpp:
(JSC::linkPolymorphicCall):
* jit/ThunkGenerators.cpp:
(JSC::emitPointerValidation):
* llint/LLIntData.cpp:
(JSC::LLInt::Data::performAssertions):
* llint/LLIntOfflineAsmConfig.h:
* parser/Lexer.cpp:
* parser/Lexer.h:
(JSC::isSafeBuiltinIdentifier):
(JSC::Lexer<T>::lexExpectIdentifier):
* runtime/ArgList.h:
(JSC::MarkedArgumentBuffer::setNeedsOverflowCheck):
(JSC::MarkedArgumentBuffer::clearNeedsOverflowCheck):
* runtime/Butterfly.h:
(JSC::ContiguousData::ContiguousData):
(JSC::ContiguousData::Data::Data):
* runtime/HashMapImpl.h:
(JSC::HashMapImpl::checkConsistency const):
(JSC::HashMapImpl::assertBufferIsEmpty const):
* runtime/JSCellInlines.h:
(JSC::JSCell::methodTable const):
* runtime/JSFunction.cpp:
* runtime/JSFunction.h:
(JSC::JSFunction::assertTypeInfoFlagInvariants):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* runtime/JSGlobalObject.h:
* runtime/JSObject.cpp:
(JSC::JSObject::visitChildren):
(JSC::JSFinalObject::visitChildren):
* runtime/JSObjectInlines.h:
(JSC::JSObject::validatePutOwnDataProperty):
* runtime/JSSegmentedVariableObject.h:
(JSC::JSSegmentedVariableObject::assertVariableIsInThisObject):
* runtime/LiteralParser.cpp:
(JSC::LiteralParser<CharType>::Lexer::lex):
* runtime/LiteralParser.h:
* runtime/Operations.h:
(JSC::scribbleFreeCells):
* runtime/OptionsList.h:
* runtime/VM.cpp:
(JSC::VM::computeCanUseJIT):
* runtime/VM.h:
(JSC::VM::canUseJIT):
* runtime/VarOffset.h:
(JSC::VarOffset::checkSanity const):
* runtime/WeakMapImpl.h:
(JSC::WeakMapImpl::checkConsistency const):
(JSC::WeakMapImpl::assertBufferIsEmpty const):
* wasm/WasmAirIRGenerator.cpp:
(JSC::Wasm::AirIRGenerator::validateInst):
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::parseAndCompile):
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser::validationFail const):
* wasm/WasmLLIntGenerator.cpp:
(JSC::Wasm::LLIntGenerator::checkConsistency):
* wasm/WasmPlan.cpp:
(JSC::Wasm::Plan::tryRemoveContextAndCancelIfLast):
* wasm/WasmSectionParser.h:
* wasm/WasmSections.h:
* wasm/WasmSignatureInlines.h:
(JSC::Wasm::SignatureInformation::get):
* wasm/WasmWorklist.cpp:
(JSC::Wasm::Worklist::enqueue):
* wasm/js/JSToWasm.cpp:
(JSC::Wasm::createJSToWasmWrapper):
* wasm/js/WebAssemblyFunction.cpp:
(JSC::WebAssemblyFunction::previousInstanceOffset const):
Source/WebCore:
Convert ASSERT_DISABLED to ASSERT_ENABLED, and fix some tests of NDEBUG that should actually test for ASSERT_ENABLED.
https://bugs.webkit.org/show_bug.cgi?id=205776
Reviewed by Saam Barati.
* Modules/fetch/FetchBodySource.cpp:
(WebCore::FetchBodySource::close):
* Modules/fetch/FetchBodySource.h:
* Modules/webdatabase/DatabaseDetails.h:
(WebCore::DatabaseDetails::DatabaseDetails):
(WebCore::DatabaseDetails::operator=):
* Modules/webdatabase/DatabaseTask.cpp:
(WebCore::DatabaseTask::performTask):
* Modules/webdatabase/DatabaseTask.h:
* Modules/webdatabase/DatabaseThread.cpp:
(WebCore::DatabaseThread::terminationRequested const):
* Modules/webgpu/WHLSL/AST/WHLSLAddressSpace.h:
(WebCore::WHLSL::AST::TypeAnnotation::TypeAnnotation):
* Modules/webgpu/WHLSL/WHLSLHighZombieFinder.cpp:
(WebCore::WHLSL::findHighZombies):
* Modules/webgpu/WHLSL/WHLSLInferTypes.cpp:
(WebCore::WHLSL::matches):
* Modules/webgpu/WHLSL/WHLSLLiteralTypeChecker.cpp:
(WebCore::WHLSL::checkLiteralTypes):
* Modules/webgpu/WHLSL/WHLSLSynthesizeConstructors.cpp:
(WebCore::WHLSL::FindAllTypes::appendNamedType):
* bindings/js/JSCallbackData.h:
* bindings/js/JSLazyEventListener.cpp:
* bindings/js/JSLazyEventListener.h:
* contentextensions/ContentExtensionCompiler.cpp:
(WebCore::ContentExtensions::compileRuleList):
* css/CSSCalculationValue.cpp:
(WebCore::CSSCalcOperationNode::primitiveType const):
* css/CSSComputedStyleDeclaration.cpp:
(WebCore::ComputedStyleExtractor::valueForPropertyInStyle):
* css/CSSPrimitiveValue.cpp:
* css/CSSSelector.cpp:
(WebCore::CSSSelector::selectorText const):
* css/CSSStyleSheet.cpp:
* dom/ActiveDOMObject.cpp:
(WebCore::ActiveDOMObject::suspendIfNeeded):
(WebCore::ActiveDOMObject::assertSuspendIfNeededWasCalled const):
* dom/ActiveDOMObject.h:
* dom/ContainerNode.cpp:
* dom/ContainerNodeAlgorithms.cpp:
* dom/ContainerNodeAlgorithms.h:
* dom/CustomElementReactionQueue.cpp:
* dom/CustomElementReactionQueue.h:
(WebCore::CustomElementReactionDisallowedScope::CustomElementReactionDisallowedScope):
(WebCore::CustomElementReactionDisallowedScope::~CustomElementReactionDisallowedScope):
* dom/Document.cpp:
(WebCore::Document::hitTest):
* dom/Document.h:
(WebCore::Document::decrementReferencingNodeCount):
* dom/Element.cpp:
(WebCore::Element::addShadowRoot):
(WebCore::Element::getURLAttribute const):
(WebCore::Element::getNonEmptyURLAttribute const):
* dom/Element.h:
* dom/ElementAndTextDescendantIterator.h:
(WebCore::ElementAndTextDescendantIterator::ElementAndTextDescendantIterator):
(WebCore::ElementAndTextDescendantIterator::dropAssertions):
(WebCore::ElementAndTextDescendantIterator::popAncestorSiblingStack):
(WebCore::ElementAndTextDescendantIterator::traverseNextSibling):
(WebCore::ElementAndTextDescendantIterator::traversePreviousSibling):
* dom/ElementDescendantIterator.h:
(WebCore::ElementDescendantIterator::ElementDescendantIterator):
(WebCore::ElementDescendantIterator::dropAssertions):
(WebCore::ElementDescendantIterator::operator++):
(WebCore::ElementDescendantIterator::operator--):
(WebCore::ElementDescendantConstIterator::ElementDescendantConstIterator):
(WebCore::ElementDescendantConstIterator::dropAssertions):
(WebCore::ElementDescendantConstIterator::operator++):
* dom/ElementIterator.h:
(WebCore::ElementIterator<ElementType>::ElementIterator):
(WebCore::ElementIterator<ElementType>::traverseNext):
(WebCore::ElementIterator<ElementType>::traversePrevious):
(WebCore::ElementIterator<ElementType>::traverseNextSibling):
(WebCore::ElementIterator<ElementType>::traversePreviousSibling):
(WebCore::ElementIterator<ElementType>::traverseNextSkippingChildren):
(WebCore::ElementIterator<ElementType>::dropAssertions):
(WebCore::ElementIterator<ElementType>::traverseAncestor):
(WebCore::ElementConstIterator<ElementType>::ElementConstIterator):
(WebCore::ElementConstIterator<ElementType>::traverseNext):
(WebCore::ElementConstIterator<ElementType>::traversePrevious):
(WebCore::ElementConstIterator<ElementType>::traverseNextSibling):
(WebCore::ElementConstIterator<ElementType>::traversePreviousSibling):
(WebCore::ElementConstIterator<ElementType>::traverseNextSkippingChildren):
(WebCore::ElementConstIterator<ElementType>::traverseAncestor):
(WebCore::ElementConstIterator<ElementType>::dropAssertions):
* dom/EventContext.cpp:
* dom/EventContext.h:
* dom/EventListener.h:
* dom/EventPath.cpp:
* dom/EventSender.h:
* dom/EventTarget.cpp:
(WebCore::EventTarget::addEventListener):
(WebCore::EventTarget::setAttributeEventListener):
(WebCore::EventTarget::innerInvokeEventListeners):
* dom/Node.cpp:
(WebCore::Node::~Node):
(WebCore::Node::moveNodeToNewDocument):
(WebCore::Node::removedLastRef):
* dom/Node.h:
(WebCore::Node::deref const):
* dom/ScriptDisallowedScope.h:
(WebCore::ScriptDisallowedScope::InMainThread::isEventDispatchAllowedInSubtree):
* dom/ScriptExecutionContext.cpp:
(WebCore::ScriptExecutionContext::~ScriptExecutionContext):
* dom/ScriptExecutionContext.h:
* dom/SelectorQuery.cpp:
(WebCore::SelectorDataList::execute const):
* dom/SlotAssignment.cpp:
(WebCore::SlotAssignment::addSlotElementByName):
(WebCore::SlotAssignment::removeSlotElementByName):
(WebCore::SlotAssignment::resolveSlotsAfterSlotMutation):
(WebCore::SlotAssignment::findFirstSlotElement):
* dom/SlotAssignment.h:
* dom/TreeScopeOrderedMap.cpp:
(WebCore::TreeScopeOrderedMap::add):
(WebCore::TreeScopeOrderedMap::get const):
* dom/TreeScopeOrderedMap.h:
* fileapi/Blob.cpp:
* fileapi/Blob.h:
* history/BackForwardCache.cpp:
(WebCore::BackForwardCache::removeAllItemsForPage):
* history/BackForwardCache.h:
* html/CanvasBase.cpp:
(WebCore::CanvasBase::notifyObserversCanvasDestroyed):
* html/CanvasBase.h:
* html/HTMLCollection.h:
(WebCore::CollectionNamedElementCache::didPopulate):
* html/HTMLSelectElement.cpp:
(WebCore:: const):
* html/HTMLTableRowsCollection.cpp:
(WebCore::assertRowIsInTable):
* html/HTMLTextFormControlElement.cpp:
(WebCore::HTMLTextFormControlElement::indexForPosition const):
* html/canvas/CanvasRenderingContext2DBase.cpp:
(WebCore::CanvasRenderingContext2DBase::~CanvasRenderingContext2DBase):
* html/parser/HTMLParserScheduler.cpp:
(WebCore::HTMLParserScheduler::HTMLParserScheduler):
(WebCore::HTMLParserScheduler::suspend):
(WebCore::HTMLParserScheduler::resume):
* html/parser/HTMLParserScheduler.h:
* html/parser/HTMLToken.h:
(WebCore::HTMLToken::beginStartTag):
(WebCore::HTMLToken::beginEndTag):
(WebCore::HTMLToken::endAttribute):
* html/parser/HTMLTreeBuilder.cpp:
(WebCore::HTMLTreeBuilder::HTMLTreeBuilder):
(WebCore::HTMLTreeBuilder::constructTree):
* html/parser/HTMLTreeBuilder.h:
(WebCore::HTMLTreeBuilder::~HTMLTreeBuilder):
* layout/FormattingContext.cpp:
(WebCore::Layout::FormattingContext::geometryForBox const):
* layout/blockformatting/BlockFormattingContext.cpp:
(WebCore::Layout::BlockFormattingContext::computeEstimatedVerticalPosition):
* layout/blockformatting/BlockFormattingContext.h:
* layout/displaytree/DisplayBox.cpp:
(WebCore::Display::Box::Box):
* layout/displaytree/DisplayBox.h:
(WebCore::Display::Box::setTopLeft):
(WebCore::Display::Box::setTop):
(WebCore::Display::Box::setLeft):
(WebCore::Display::Box::setContentBoxHeight):
(WebCore::Display::Box::setContentBoxWidth):
(WebCore::Display::Box::setHorizontalMargin):
(WebCore::Display::Box::setVerticalMargin):
(WebCore::Display::Box::setHorizontalComputedMargin):
(WebCore::Display::Box::setBorder):
(WebCore::Display::Box::setPadding):
* layout/displaytree/DisplayInlineRect.h:
(WebCore::Display::InlineRect::InlineRect):
(WebCore::Display::InlineRect::setTopLeft):
(WebCore::Display::InlineRect::setTop):
(WebCore::Display::InlineRect::setBottom):
(WebCore::Display::InlineRect::setLeft):
(WebCore::Display::InlineRect::setWidth):
(WebCore::Display::InlineRect::setHeight):
* layout/displaytree/DisplayLineBox.h:
(WebCore::Display::LineBox::LineBox):
(WebCore::Display::LineBox::setBaselineOffsetIfGreater):
(WebCore::Display::LineBox::resetBaseline):
(WebCore::Display::LineBox::Baseline::Baseline):
(WebCore::Display::LineBox::Baseline::setAscent):
(WebCore::Display::LineBox::Baseline::setDescent):
(WebCore::Display::LineBox::Baseline::reset):
* layout/displaytree/DisplayRect.h:
(WebCore::Display::Rect::Rect):
(WebCore::Display::Rect::setTopLeft):
(WebCore::Display::Rect::setTop):
(WebCore::Display::Rect::setLeft):
(WebCore::Display::Rect::setWidth):
(WebCore::Display::Rect::setHeight):
(WebCore::Display::Rect::setSize):
(WebCore::Display::Rect::clone const):
* layout/floats/FloatingContext.cpp:
* layout/inlineformatting/InlineLineBuilder.cpp:
(WebCore::Layout::LineBuilder::CollapsibleContent::collapse):
* layout/tableformatting/TableGrid.cpp:
(WebCore::Layout::TableGrid::Column::setWidthConstraints):
(WebCore::Layout::TableGrid::Column::setLogicalWidth):
(WebCore::Layout::TableGrid::Column::setLogicalLeft):
* layout/tableformatting/TableGrid.h:
* loader/DocumentLoader.cpp:
(WebCore::DocumentLoader::continueAfterContentPolicy):
(WebCore::DocumentLoader::attachToFrame):
(WebCore::DocumentLoader::detachFromFrame):
(WebCore::DocumentLoader::addSubresourceLoader):
* loader/DocumentLoader.h:
* loader/ImageLoader.cpp:
* loader/cache/CachedResource.h:
* loader/cache/MemoryCache.cpp:
(WebCore::MemoryCache::lruListFor):
(WebCore::MemoryCache::removeFromLRUList):
* page/FrameView.cpp:
(WebCore::FrameView::updateLayoutAndStyleIfNeededRecursive):
* page/FrameViewLayoutContext.cpp:
* page/FrameViewLayoutContext.h:
* page/Page.cpp:
* page/Page.h:
* page/ViewportConfiguration.cpp:
* page/ViewportConfiguration.h:
* page/mac/EventHandlerMac.mm:
(WebCore::CurrentEventScope::CurrentEventScope):
* platform/DateComponents.cpp:
(WebCore::DateComponents::toStringForTime const):
* platform/ScrollableArea.cpp:
* platform/SharedBuffer.cpp:
(WebCore::SharedBuffer::combineIntoOneSegment const):
* platform/SharedBuffer.h:
* platform/Supplementable.h:
* platform/Timer.cpp:
(WebCore::TimerBase::checkHeapIndex const):
(WebCore::TimerBase::updateHeapIfNeeded):
* platform/graphics/BitmapImage.cpp:
* platform/graphics/BitmapImage.h:
* platform/graphics/Image.h:
* platform/graphics/ShadowBlur.cpp:
(WebCore::ScratchBuffer::ScratchBuffer):
(WebCore::ScratchBuffer::getScratchBuffer):
(WebCore::ScratchBuffer::scheduleScratchBufferPurge):
* platform/graphics/ca/win/CACFLayerTreeHost.cpp:
(WebCore::CACFLayerTreeHost::setWindow):
* platform/graphics/ca/win/CACFLayerTreeHost.h:
* platform/graphics/cg/ImageBufferDataCG.cpp:
(WebCore::ImageBufferData::putData):
* platform/graphics/cocoa/FontCacheCoreText.cpp:
* platform/graphics/gstreamer/GstAllocatorFastMalloc.cpp:
(gstAllocatorFastMallocFree):
* platform/graphics/nicosia/cairo/NicosiaPaintingContextCairo.cpp:
(Nicosia::PaintingContextCairo::ForPainting::ForPainting):
* platform/graphics/nicosia/texmap/NicosiaBackingStoreTextureMapperImpl.cpp:
(Nicosia::BackingStoreTextureMapperImpl::createTile):
* platform/graphics/nicosia/texmap/NicosiaContentLayerTextureMapperImpl.cpp:
(Nicosia::ContentLayerTextureMapperImpl::~ContentLayerTextureMapperImpl):
* platform/graphics/win/GradientDirect2D.cpp:
(WebCore::Gradient::fill):
* platform/graphics/win/ImageBufferDataDirect2D.cpp:
(WebCore::ImageBufferData::putData):
* platform/graphics/win/PathDirect2D.cpp:
(WebCore::Path::appendGeometry):
(WebCore::Path::Path):
(WebCore::Path::operator=):
(WebCore::Path::strokeContains const):
(WebCore::Path::transform):
* platform/graphics/win/PlatformContextDirect2D.cpp:
(WebCore::PlatformContextDirect2D::setTags):
* platform/mediastream/MediaStreamTrackPrivate.h:
* platform/mediastream/RealtimeOutgoingAudioSource.cpp:
(WebCore::RealtimeOutgoingAudioSource::~RealtimeOutgoingAudioSource):
* platform/mediastream/RealtimeOutgoingVideoSource.cpp:
(WebCore::RealtimeOutgoingVideoSource::~RealtimeOutgoingVideoSource):
* platform/network/HTTPParsers.cpp:
(WebCore::isCrossOriginSafeHeader):
* platform/sql/SQLiteDatabase.cpp:
* platform/sql/SQLiteDatabase.h:
* platform/sql/SQLiteStatement.cpp:
(WebCore::SQLiteStatement::SQLiteStatement):
(WebCore::SQLiteStatement::prepare):
(WebCore::SQLiteStatement::finalize):
* platform/sql/SQLiteStatement.h:
* platform/win/COMPtr.h:
* rendering/ComplexLineLayout.cpp:
(WebCore::ComplexLineLayout::removeInlineBox const):
* rendering/FloatingObjects.cpp:
(WebCore::FloatingObject::FloatingObject):
(WebCore::FloatingObjects::addPlacedObject):
(WebCore::FloatingObjects::removePlacedObject):
* rendering/FloatingObjects.h:
* rendering/GridTrackSizingAlgorithm.cpp:
* rendering/GridTrackSizingAlgorithm.h:
* rendering/LayoutDisallowedScope.cpp:
* rendering/LayoutDisallowedScope.h:
* rendering/RenderBlock.cpp:
* rendering/RenderBlock.h:
* rendering/RenderBlockFlow.cpp:
(WebCore::RenderBlockFlow::layoutBlockChild):
(WebCore::RenderBlockFlow::removeFloatingObject):
(WebCore::RenderBlockFlow::ensureLineBoxes):
* rendering/RenderBoxModelObject.cpp:
* rendering/RenderDeprecatedFlexibleBox.cpp:
(WebCore::RenderDeprecatedFlexibleBox::layoutBlock):
* rendering/RenderElement.cpp:
* rendering/RenderGeometryMap.cpp:
(WebCore::RenderGeometryMap::mapToContainer const):
* rendering/RenderGrid.cpp:
(WebCore::RenderGrid::placeItemsOnGrid const):
(WebCore::RenderGrid::baselinePosition const):
* rendering/RenderInline.cpp:
(WebCore::RenderInline::willBeDestroyed):
* rendering/RenderLayer.cpp:
(WebCore::ClipRectsCache::ClipRectsCache):
(WebCore::RenderLayer::RenderLayer):
(WebCore::RenderLayer::paintList):
(WebCore::RenderLayer::hitTestLayer):
(WebCore::RenderLayer::updateClipRects):
(WebCore::RenderLayer::calculateClipRects const):
* rendering/RenderLayer.h:
* rendering/RenderLayerBacking.cpp:
(WebCore::traverseVisibleNonCompositedDescendantLayers):
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::computeCompositingRequirements):
(WebCore::RenderLayerCompositor::traverseUnchangedSubtree):
(WebCore::RenderLayerCompositor::updateBackingAndHierarchy):
(WebCore::RenderLayerCompositor::addDescendantsToOverlapMapRecursive const):
(WebCore::RenderLayerCompositor::recursiveRepaintLayer):
(WebCore::RenderLayerCompositor::layerHas3DContent const):
* rendering/RenderLayoutState.cpp:
(WebCore::RenderLayoutState::RenderLayoutState):
(WebCore::RenderLayoutState::computeOffsets):
(WebCore::RenderLayoutState::addLayoutDelta):
* rendering/RenderLayoutState.h:
(WebCore::RenderLayoutState::RenderLayoutState):
* rendering/RenderObject.cpp:
(WebCore::RenderObject::RenderObject):
(WebCore::RenderObject::~RenderObject):
(WebCore::RenderObject::clearNeedsLayout):
* rendering/RenderObject.h:
* rendering/RenderQuote.cpp:
(WebCore::quotesForLanguage):
* rendering/RenderTableCell.h:
* rendering/RenderTableSection.cpp:
(WebCore::RenderTableSection::computeOverflowFromCells):
* rendering/RenderTextLineBoxes.cpp:
(WebCore::RenderTextLineBoxes::checkConsistency const):
* rendering/RenderTextLineBoxes.h:
* rendering/line/BreakingContext.h:
(WebCore::tryHyphenating):
* rendering/style/GridArea.h:
(WebCore::GridSpan::GridSpan):
* rendering/style/RenderStyle.cpp:
(WebCore::RenderStyle::~RenderStyle):
* rendering/style/RenderStyle.h:
* rendering/updating/RenderTreeBuilderRuby.cpp:
(WebCore::RenderTreeBuilder::Ruby::detach):
* rendering/updating/RenderTreePosition.cpp:
(WebCore::RenderTreePosition::computeNextSibling):
* rendering/updating/RenderTreePosition.h:
* svg/SVGToOTFFontConversion.cpp:
(WebCore::SVGToOTFFontConverter::Placeholder::Placeholder):
(WebCore::SVGToOTFFontConverter::Placeholder::populate):
(WebCore::SVGToOTFFontConverter::appendCFFTable):
(WebCore::SVGToOTFFontConverter::firstGlyph const):
(WebCore::SVGToOTFFontConverter::appendKERNTable):
* svg/SVGTransformDistance.cpp:
(WebCore::SVGTransformDistance::SVGTransformDistance):
(WebCore::SVGTransformDistance::scaledDistance const):
(WebCore::SVGTransformDistance::addSVGTransforms):
(WebCore::SVGTransformDistance::addToSVGTransform const):
(WebCore::SVGTransformDistance::distance const):
* svg/graphics/SVGImage.cpp:
(WebCore::SVGImage::nativeImage):
* testing/InternalSettings.cpp:
* workers/service/ServiceWorkerJob.h:
* worklets/PaintWorkletGlobalScope.h:
(WebCore::PaintWorkletGlobalScope::~PaintWorkletGlobalScope):
* xml/XPathStep.cpp:
Source/WebKit:
Convert ASSERT_DISABLED to ASSERT_ENABLED, and fix some tests of NDEBUG that should actually test for ASSERT_ENABLED.
https://bugs.webkit.org/show_bug.cgi?id=205776
Reviewed by Saam Barati.
* NetworkProcess/NetworkSession.cpp:
(WebKit::NetworkSession::invalidateAndCancel):
* NetworkProcess/NetworkSession.h:
* NetworkProcess/cache/NetworkCacheStorage.cpp:
(WebKit::NetworkCache::Storage::setCapacity):
* NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(toNSURLSessionResponseDisposition):
(WebKit::NetworkSessionCocoa::NetworkSessionCocoa):
* Platform/IPC/Connection.cpp:
(IPC::Connection::waitForMessage):
* Platform/IPC/MessageReceiver.h:
(IPC::MessageReceiver::willBeAddedToMessageReceiverMap):
(IPC::MessageReceiver::willBeRemovedFromMessageReceiverMap):
* Platform/IPC/cocoa/ConnectionCocoa.mm:
(IPC::readFromMachPort):
* Platform/mac/MachUtilities.cpp:
(setMachExceptionPort):
* Shared/API/APIClient.h:
(API::Client::Client):
* Shared/API/Cocoa/WKRemoteObjectCoder.mm:
* Shared/Cocoa/ArgumentCodersCocoa.h:
* Shared/SharedStringHashTableReadOnly.cpp:
* UIProcess/BackingStore.cpp:
(WebKit::BackingStore::incorporateUpdate):
* UIProcess/GenericCallback.h:
* UIProcess/Launcher/mac/ProcessLauncherMac.mm:
(WebKit::ProcessLauncher::launchProcess):
* UIProcess/PageLoadState.h:
(WebKit::PageLoadState::Transaction::Token::Token):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::~WebPageProxy):
* WebProcess/Network/WebResourceLoader.cpp:
(WebKit::WebResourceLoader::didReceiveResponse):
* WebProcess/Network/WebResourceLoader.h:
* WebProcess/Plugins/Netscape/NetscapePluginStream.cpp:
(WebKit::NetscapePluginStream::NetscapePluginStream):
(WebKit::NetscapePluginStream::notifyAndDestroyStream):
* WebProcess/Plugins/Netscape/NetscapePluginStream.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::runModal):
* WebProcess/WebProcess.cpp:
(WebKit::checkDocumentsCaptureStateConsistency):
* WebProcess/cocoa/WebProcessCocoa.mm:
(WebKit::WebProcess::updateProcessName):
Source/WebKitLegacy:
Convert ASSERT_DISABLED to ASSERT_ENABLED, and fix some tests of NDEBUG that should actually test for ASSERT_ENABLED.
https://bugs.webkit.org/show_bug.cgi?id=205776
Reviewed by Saam Barati.
* Storage/StorageAreaImpl.cpp:
(WebKit::StorageAreaImpl::StorageAreaImpl):
(WebKit::StorageAreaImpl::close):
* Storage/StorageAreaImpl.h:
Source/WebKitLegacy/mac:
Convert ASSERT_DISABLED to ASSERT_ENABLED, and fix some tests of NDEBUG that should actually test for ASSERT_ENABLED.
https://bugs.webkit.org/show_bug.cgi?id=205776
Reviewed by Saam Barati.
* History/WebHistory.mm:
(-[WebHistoryPrivate removeItemForURLString:]):
* WebView/WebFrame.mm:
Source/WebKitLegacy/win:
Convert ASSERT_DISABLED to ASSERT_ENABLED, and fix some tests of NDEBUG that should actually test for ASSERT_ENABLED.
https://bugs.webkit.org/show_bug.cgi?id=205776
Reviewed by Saam Barati.
* WebKitQuartzCoreAdditions/CAD3DRenderer.cpp:
(WKQCA::CAD3DRenderer::swapChain):
(WKQCA::CAD3DRenderer::initialize):
* WebKitQuartzCoreAdditions/CAD3DRenderer.h:
* WebView.cpp:
(WebView::Release):
* WebView.h:
Source/WTF:
Convert ASSERT_DISABLED to ASSERT_ENABLED, and fix some tests of NDEBUG that should actually test for ASSERT_ENABLED.
https://bugs.webkit.org/show_bug.cgi?id=205776
Reviewed by Saam Barati.
This patch did the following changes:
1. Replaced ASSERT_DISABLED with ASSERT_ENABLED. This change does away
with the need for the double negative !ASSERT_DISABLED test that is commonly
used all over the code, thereby improving code readability.
In Assertions.h, there is also BACKTRACE_DISABLED, ASSERT_MSG_DISABLED,
ASSERT_ARG_DISABLED, FATAL_DISABLED, ERROR_DISABLED, LOG_DISABLED, and
RELEASE_LOG_DISABLED. We should replace those with ..._ENABLED equivalents
as well. We'll do that in another patch. For now, they are left as is to
minimize the size of this patch.
See https://bugs.webkit.org/show_bug.cgi?id=205780.
2. Fixed some code was guarded with "#ifndef NDEBUG" that should actually be
guarded by "#if ASSERT_ENABLED" instead.
3. In cases where the change is minimal, we move some code around so that we can
test for "#if ASSERT_ENABLED" instead of "#if !ASSERT_ENABLED".
* wtf/Assertions.h:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/BitVector.h:
* wtf/BlockObjCExceptions.mm:
(ReportBlockedObjCException):
* wtf/BloomFilter.h:
* wtf/CallbackAggregator.h:
(WTF::CallbackAggregator::CallbackAggregator):
* wtf/CheckedArithmetic.h:
(WTF::observesOverflow<AssertNoOverflow>):
* wtf/CheckedBoolean.h:
(CheckedBoolean::CheckedBoolean):
(CheckedBoolean::operator bool):
* wtf/CompletionHandler.h:
(WTF::CompletionHandler<Out):
* wtf/DateMath.cpp:
(WTF::initializeDates):
* wtf/Gigacage.cpp:
(Gigacage::tryAllocateZeroedVirtualPages):
* wtf/HashTable.h:
(WTF::KeyTraits>::checkKey):
(WTF::KeyTraits>::checkTableConsistencyExceptSize const):
* wtf/LoggerHelper.h:
* wtf/NaturalLoops.h:
(WTF::NaturalLoops::headerOf const):
* wtf/NeverDestroyed.h:
(WTF::LazyNeverDestroyed::construct):
* wtf/OptionSet.h:
(WTF::OptionSet::OptionSet):
* wtf/Platform.h:
* wtf/PtrTag.h:
* wtf/RefCounted.h:
(WTF::RefCountedBase::disableThreadingChecks):
(WTF::RefCountedBase::enableThreadingChecksGlobally):
(WTF::RefCountedBase::RefCountedBase):
(WTF::RefCountedBase::applyRefDerefThreadingCheck const):
* wtf/SingleRootGraph.h:
(WTF::SingleRootGraph::assertIsConsistent const):
* wtf/SizeLimits.cpp:
* wtf/StackBounds.h:
(WTF::StackBounds::checkConsistency const):
* wtf/URLParser.cpp:
(WTF::URLParser::URLParser):
(WTF::URLParser::domainToASCII):
* wtf/ValueCheck.h:
* wtf/Vector.h:
(WTF::Malloc>::checkConsistency):
* wtf/WeakHashSet.h:
* wtf/WeakPtr.h:
(WTF::WeakPtrImpl::WeakPtrImpl):
(WTF::WeakPtrFactory::WeakPtrFactory):
* wtf/text/AtomStringImpl.cpp:
* wtf/text/AtomStringImpl.h:
* wtf/text/StringBuilder.cpp:
(WTF::StringBuilder::reifyString const):
* wtf/text/StringBuilder.h:
* wtf/text/StringCommon.h:
(WTF::hasPrefixWithLettersIgnoringASCIICaseCommon):
* wtf/text/StringHasher.h:
(WTF::StringHasher::addCharacters):
* wtf/text/StringImpl.h:
* wtf/text/SymbolImpl.h:
* wtf/text/UniquedStringImpl.h:
Tools:
Remove WebsiteDataStore::setServiceWorkerRegistrationDirectory
https://bugs.webkit.org/show_bug.cgi?id=205754
Patch by Alex Christensen <achristensen@webkit.org> on 2020-01-06
Reviewed by Youenn Fablet.
* TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::websiteDataStore):
(WTR::TestController::platformAdjustContext):
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::initializeWebViewConfiguration):
Canonical link: https://commits.webkit.org/218957@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@254087 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-01-06 22:24:50 +00:00
|
|
|
if (ASSERT_ENABLED) {
|
2014-09-04 21:08:38 +00:00
|
|
|
size_t expectedResult = findBitSimple(index, value);
|
|
|
|
if (result != expectedResult) {
|
|
|
|
dataLog("findBit(", index, ", ", value, ") on ", *this, " should have gotten ", expectedResult, " but got ", result, "\n");
|
|
|
|
ASSERT_NOT_REACHED();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2013-10-23 18:22:09 +00:00
|
|
|
WTF_EXPORT_PRIVATE void dump(PrintStream& out) const;
|
|
|
|
|
|
|
|
enum EmptyValueTag { EmptyValue };
|
|
|
|
enum DeletedValueTag { DeletedValue };
|
|
|
|
|
|
|
|
BitVector(EmptyValueTag)
|
|
|
|
: m_bitsOrPointer(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
BitVector(DeletedValueTag)
|
|
|
|
: m_bitsOrPointer(1)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isEmptyValue() const { return !m_bitsOrPointer; }
|
|
|
|
bool isDeletedValue() const { return m_bitsOrPointer == 1; }
|
|
|
|
|
|
|
|
bool isEmptyOrDeletedValue() const { return m_bitsOrPointer <= 1; }
|
|
|
|
|
|
|
|
bool operator==(const BitVector& other) const
|
|
|
|
{
|
|
|
|
if (isInline() && other.isInline())
|
|
|
|
return m_bitsOrPointer == other.m_bitsOrPointer;
|
|
|
|
return equalsSlowCase(other);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned hash() const
|
|
|
|
{
|
|
|
|
// This is a very simple hash. Just xor together the words that hold the various
|
|
|
|
// bits and then compute the hash. This makes it very easy to deal with bitvectors
|
|
|
|
// that have a lot of trailing zero's.
|
|
|
|
uintptr_t value;
|
|
|
|
if (isInline())
|
|
|
|
value = cleanseInlineBits(m_bitsOrPointer);
|
|
|
|
else
|
|
|
|
value = hashSlowCase();
|
|
|
|
return IntHash<uintptr_t>::hash(value);
|
|
|
|
}
|
2011-10-11 23:50:26 +00:00
|
|
|
|
It should be possible to run liveness over registers without also tracking Tmps
https://bugs.webkit.org/show_bug.cgi?id=152963
Reviewed by Saam Barati.
Source/JavaScriptCore:
This adds a RegLivenessAdapter so that we can run Liveness over registers. This makes it
easier to write certain kinds of phases, like ReportUsedRegisters. I anticipate writing more
code like that for handling cold function calls. It also makes code like that somewhat more
scalable, since we're no longer using HashSets.
Currently, the way we track sets of registers is with a BitVector. Normally, we use the
RegisterSet class, which wraps BitVector, so that we can add()/contains() on Reg's. But in
the liveness analysis, everything gets turned into an index. So, we want to use BitVector
directly. To do that, I needed to make the BitVector API look a bit more like a set API. I
think that this is good, because the lack of set methods (add/remove/contains) has caused
bugs in the past. This makes BitVector have methods both for set operations on bits and array
operations on bits. I think that's good, since BitVector gets used in both contexts.
* b3/B3IndexSet.h:
(JSC::B3::IndexSet::Iterable::iterator::iterator):
(JSC::B3::IndexSet::Iterable::begin):
(JSC::B3::IndexSet::dump):
* b3/air/AirInstInlines.h:
(JSC::B3::Air::ForEach<Tmp>::forEach):
(JSC::B3::Air::ForEach<Arg>::forEach):
(JSC::B3::Air::ForEach<Reg>::forEach):
(JSC::B3::Air::Inst::forEach):
* b3/air/AirLiveness.h:
(JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter):
(JSC::B3::Air::RegLivenessAdapter::maxIndex):
(JSC::B3::Air::RegLivenessAdapter::acceptsType):
(JSC::B3::Air::RegLivenessAdapter::valueToIndex):
(JSC::B3::Air::RegLivenessAdapter::indexToValue):
* b3/air/AirReportUsedRegisters.cpp:
(JSC::B3::Air::reportUsedRegisters):
* jit/Reg.h:
(JSC::Reg::next):
(JSC::Reg::index):
(JSC::Reg::maxIndex):
(JSC::Reg::isSet):
(JSC::Reg::operator bool):
* jit/RegisterSet.h:
(JSC::RegisterSet::forEach):
Source/WTF:
Add set methods (add/contains/remove) to BitVector, since it gets used as a set in a lot of
places. This also makes BitVector a drop-in replacement for HashSet<unsigned> in a lot of
places.
Also made the iterator methods of BitVector live on BitVector directly rather than behind the
thing returned from setBits(). This makes sense since that makes BitVector even more of a
drop-in for HashSet. It's not harmful since we've never added any other mode of iterating a
BitVector other than this, so it doesn't make sense to make it harder to access.
* wtf/BitVector.h:
(WTF::BitVector::get):
(WTF::BitVector::contains):
(WTF::BitVector::set):
(WTF::BitVector::add):
(WTF::BitVector::ensureSizeAndSet):
(WTF::BitVector::clear):
(WTF::BitVector::remove):
(WTF::BitVector::hash):
(WTF::BitVector::iterator::iterator):
(WTF::BitVector::iterator::operator*):
(WTF::BitVector::iterator::operator++):
(WTF::BitVector::iterator::operator==):
(WTF::BitVector::iterator::operator!=):
(WTF::BitVector::begin):
(WTF::BitVector::end):
(WTF::BitVector::bitsInPointer):
(WTF::BitVector::SetBitsIterable::SetBitsIterable): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::iterator): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator*): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator++): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator==): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator!=): Deleted.
(WTF::BitVector::SetBitsIterable::begin): Deleted.
(WTF::BitVector::SetBitsIterable::end): Deleted.
(WTF::BitVector::setBits): Deleted.
Canonical link: https://commits.webkit.org/171043@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@194834 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-01-11 00:58:34 +00:00
|
|
|
class iterator {
|
2019-08-12 20:57:15 +00:00
|
|
|
WTF_MAKE_FAST_ALLOCATED;
|
FTL should sink PutLocals
https://bugs.webkit.org/show_bug.cgi?id=137168
Reviewed by Oliver Hunt.
Source/JavaScriptCore:
We've known for a while that our PutLocal situation was sub-optimal. We emit them anytime we
"pass" arguments to an inlined function call, because we need to enable the runtime to grab
those arguments when doing foo.arguments where foo is inlined: our engine doesn't deoptimize
in that case but rather just relies on the arguments being flushed (i.e. a copy of their
values is spilled) at a well-known place in a well-known format.
The PutLocals incur two costs: (1) they are store instructions and stores ain't free, and (2)
they look like escaping sites and so they inhibit object allocation sinking.
But in most cases, the PutLocals are unnecessary because the inlined code never performs any
side effect that could transitively lead to function.arguments. Even if the inlined code
could do such a side effect, it may be on a rare path so there is no need to penalize the
entire function.
This patch implements one solution to the PutLocal problem: it aggressively sinks PutLocals
to the latest possible point. This is even more aggressive than the object allocation
sinking. That sinking algorithm avoids creating situations where an object could be
materialized more than one along any path. PutLocal sinking, on the other hand, doesn't avoid
this at all - both to make the phase cheaper and simpler and to make it more aggressive.
Every PutLocal is sunk no matter what.
The upside of this patch is that it eliminates many PutLocals: many of them are sunk "past
their death", thus eliminating them completely. Others are sunk to rare paths. This enables a
lot of object allocation sinking and it removes a lot of pointless store instructions.
It also has downsites. Sinking PutLocals increases register pressure because it increases the
live ranges of things like inlined arguments.
This patch is a net performance win in its current form: 1% SunSpider regression, 2% OctaneV2
progression, 0.6% Kraken regression, 1% AsmBench progression, and 0.5% CompressionBench
regression. The biggest win is on Octane/raytrace, which improves by 27%.
Relanding after fixing internal builds. We have to be careful about implicit casts from int64
to int32.
* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.h:
* bytecode/Operands.h:
(JSC::Operands::dump): Deleted.
* bytecode/OperandsInlines.h:
(JSC::Traits>::dump):
* bytecode/VirtualRegister.h:
(JSC::VirtualRegister::isHeader):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
* dfg/DFGClobberSet.h:
(JSC::DFG::ClobberSetAdd::operator()):
(JSC::DFG::ClobberSetOverlaps::operator()):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
(JSC::DFG::NoOpClobberize::operator()):
(JSC::DFG::CheckClobberize::operator()):
(JSC::DFG::AbstractHeapOverlaps::operator()):
(JSC::DFG::ReadMethodClobberize::operator()):
(JSC::DFG::WriteMethodClobberize::operator()):
(JSC::DFG::DefMethodClobberize::operator()):
* dfg/DFGFlushFormat.h:
(JSC::DFG::merge):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::Graph):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::capturedVarsFor):
* dfg/DFGObjectAllocationSinkingPhase.cpp:
(JSC::DFG::ObjectAllocationSinkingPhase::determineMaterializationPoints):
(JSC::DFG::ObjectAllocationSinkingPhase::placeMaterializationPoints):
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
* dfg/DFGPreciseLocalClobberize.h: Added.
(JSC::DFG::PreciseLocalClobberizeAdaptor::PreciseLocalClobberizeAdaptor):
(JSC::DFG::PreciseLocalClobberizeAdaptor::read):
(JSC::DFG::PreciseLocalClobberizeAdaptor::write):
(JSC::DFG::PreciseLocalClobberizeAdaptor::def):
(JSC::DFG::PreciseLocalClobberizeAdaptor::callIfAppropriate):
(JSC::DFG::PreciseLocalClobberizeAdaptor::readTop):
(JSC::DFG::PreciseLocalClobberizeAdaptor::writeTop):
(JSC::DFG::forEachLocalReadByUnwind):
(JSC::DFG::preciseLocalClobberize):
* dfg/DFGPutLocalSinkingPhase.cpp: Added.
(JSC::DFG::performPutLocalSinking):
* dfg/DFGPutLocalSinkingPhase.h: Added.
* dfg/DFGSSACalculator.h:
(JSC::DFG::SSACalculator::computePhis):
* dfg/DFGValidate.cpp:
Source/WTF:
Make the set bits of a BitVector iterable.
* wtf/BitVector.h:
(WTF::BitVector::SetBitsIterable::SetBitsIterable):
(WTF::BitVector::SetBitsIterable::iterator::iterator):
(WTF::BitVector::SetBitsIterable::iterator::operator*):
(WTF::BitVector::SetBitsIterable::iterator::operator++):
(WTF::BitVector::SetBitsIterable::iterator::operator==):
(WTF::BitVector::SetBitsIterable::iterator::operator!=):
(WTF::BitVector::SetBitsIterable::begin):
(WTF::BitVector::SetBitsIterable::end):
(WTF::BitVector::setBits):
LayoutTests:
* js/regress/elidable-new-object-then-call-expected.txt: Added.
* js/regress/elidable-new-object-then-call.html: Added.
* js/regress/script-tests/elidable-new-object-then-call.js: Added.
(sumOfArithSeries):
(bar):
(foo):
Canonical link: https://commits.webkit.org/155232@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@174318 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2014-10-04 17:18:25 +00:00
|
|
|
public:
|
It should be possible to run liveness over registers without also tracking Tmps
https://bugs.webkit.org/show_bug.cgi?id=152963
Reviewed by Saam Barati.
Source/JavaScriptCore:
This adds a RegLivenessAdapter so that we can run Liveness over registers. This makes it
easier to write certain kinds of phases, like ReportUsedRegisters. I anticipate writing more
code like that for handling cold function calls. It also makes code like that somewhat more
scalable, since we're no longer using HashSets.
Currently, the way we track sets of registers is with a BitVector. Normally, we use the
RegisterSet class, which wraps BitVector, so that we can add()/contains() on Reg's. But in
the liveness analysis, everything gets turned into an index. So, we want to use BitVector
directly. To do that, I needed to make the BitVector API look a bit more like a set API. I
think that this is good, because the lack of set methods (add/remove/contains) has caused
bugs in the past. This makes BitVector have methods both for set operations on bits and array
operations on bits. I think that's good, since BitVector gets used in both contexts.
* b3/B3IndexSet.h:
(JSC::B3::IndexSet::Iterable::iterator::iterator):
(JSC::B3::IndexSet::Iterable::begin):
(JSC::B3::IndexSet::dump):
* b3/air/AirInstInlines.h:
(JSC::B3::Air::ForEach<Tmp>::forEach):
(JSC::B3::Air::ForEach<Arg>::forEach):
(JSC::B3::Air::ForEach<Reg>::forEach):
(JSC::B3::Air::Inst::forEach):
* b3/air/AirLiveness.h:
(JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter):
(JSC::B3::Air::RegLivenessAdapter::maxIndex):
(JSC::B3::Air::RegLivenessAdapter::acceptsType):
(JSC::B3::Air::RegLivenessAdapter::valueToIndex):
(JSC::B3::Air::RegLivenessAdapter::indexToValue):
* b3/air/AirReportUsedRegisters.cpp:
(JSC::B3::Air::reportUsedRegisters):
* jit/Reg.h:
(JSC::Reg::next):
(JSC::Reg::index):
(JSC::Reg::maxIndex):
(JSC::Reg::isSet):
(JSC::Reg::operator bool):
* jit/RegisterSet.h:
(JSC::RegisterSet::forEach):
Source/WTF:
Add set methods (add/contains/remove) to BitVector, since it gets used as a set in a lot of
places. This also makes BitVector a drop-in replacement for HashSet<unsigned> in a lot of
places.
Also made the iterator methods of BitVector live on BitVector directly rather than behind the
thing returned from setBits(). This makes sense since that makes BitVector even more of a
drop-in for HashSet. It's not harmful since we've never added any other mode of iterating a
BitVector other than this, so it doesn't make sense to make it harder to access.
* wtf/BitVector.h:
(WTF::BitVector::get):
(WTF::BitVector::contains):
(WTF::BitVector::set):
(WTF::BitVector::add):
(WTF::BitVector::ensureSizeAndSet):
(WTF::BitVector::clear):
(WTF::BitVector::remove):
(WTF::BitVector::hash):
(WTF::BitVector::iterator::iterator):
(WTF::BitVector::iterator::operator*):
(WTF::BitVector::iterator::operator++):
(WTF::BitVector::iterator::operator==):
(WTF::BitVector::iterator::operator!=):
(WTF::BitVector::begin):
(WTF::BitVector::end):
(WTF::BitVector::bitsInPointer):
(WTF::BitVector::SetBitsIterable::SetBitsIterable): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::iterator): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator*): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator++): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator==): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator!=): Deleted.
(WTF::BitVector::SetBitsIterable::begin): Deleted.
(WTF::BitVector::SetBitsIterable::end): Deleted.
(WTF::BitVector::setBits): Deleted.
Canonical link: https://commits.webkit.org/171043@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@194834 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-01-11 00:58:34 +00:00
|
|
|
iterator()
|
|
|
|
: m_bitVector(nullptr)
|
|
|
|
, m_index(0)
|
FTL should sink PutLocals
https://bugs.webkit.org/show_bug.cgi?id=137168
Reviewed by Oliver Hunt.
Source/JavaScriptCore:
We've known for a while that our PutLocal situation was sub-optimal. We emit them anytime we
"pass" arguments to an inlined function call, because we need to enable the runtime to grab
those arguments when doing foo.arguments where foo is inlined: our engine doesn't deoptimize
in that case but rather just relies on the arguments being flushed (i.e. a copy of their
values is spilled) at a well-known place in a well-known format.
The PutLocals incur two costs: (1) they are store instructions and stores ain't free, and (2)
they look like escaping sites and so they inhibit object allocation sinking.
But in most cases, the PutLocals are unnecessary because the inlined code never performs any
side effect that could transitively lead to function.arguments. Even if the inlined code
could do such a side effect, it may be on a rare path so there is no need to penalize the
entire function.
This patch implements one solution to the PutLocal problem: it aggressively sinks PutLocals
to the latest possible point. This is even more aggressive than the object allocation
sinking. That sinking algorithm avoids creating situations where an object could be
materialized more than one along any path. PutLocal sinking, on the other hand, doesn't avoid
this at all - both to make the phase cheaper and simpler and to make it more aggressive.
Every PutLocal is sunk no matter what.
The upside of this patch is that it eliminates many PutLocals: many of them are sunk "past
their death", thus eliminating them completely. Others are sunk to rare paths. This enables a
lot of object allocation sinking and it removes a lot of pointless store instructions.
It also has downsites. Sinking PutLocals increases register pressure because it increases the
live ranges of things like inlined arguments.
This patch is a net performance win in its current form: 1% SunSpider regression, 2% OctaneV2
progression, 0.6% Kraken regression, 1% AsmBench progression, and 0.5% CompressionBench
regression. The biggest win is on Octane/raytrace, which improves by 27%.
Relanding after fixing internal builds. We have to be careful about implicit casts from int64
to int32.
* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.h:
* bytecode/Operands.h:
(JSC::Operands::dump): Deleted.
* bytecode/OperandsInlines.h:
(JSC::Traits>::dump):
* bytecode/VirtualRegister.h:
(JSC::VirtualRegister::isHeader):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
* dfg/DFGClobberSet.h:
(JSC::DFG::ClobberSetAdd::operator()):
(JSC::DFG::ClobberSetOverlaps::operator()):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
(JSC::DFG::NoOpClobberize::operator()):
(JSC::DFG::CheckClobberize::operator()):
(JSC::DFG::AbstractHeapOverlaps::operator()):
(JSC::DFG::ReadMethodClobberize::operator()):
(JSC::DFG::WriteMethodClobberize::operator()):
(JSC::DFG::DefMethodClobberize::operator()):
* dfg/DFGFlushFormat.h:
(JSC::DFG::merge):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::Graph):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::capturedVarsFor):
* dfg/DFGObjectAllocationSinkingPhase.cpp:
(JSC::DFG::ObjectAllocationSinkingPhase::determineMaterializationPoints):
(JSC::DFG::ObjectAllocationSinkingPhase::placeMaterializationPoints):
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
* dfg/DFGPreciseLocalClobberize.h: Added.
(JSC::DFG::PreciseLocalClobberizeAdaptor::PreciseLocalClobberizeAdaptor):
(JSC::DFG::PreciseLocalClobberizeAdaptor::read):
(JSC::DFG::PreciseLocalClobberizeAdaptor::write):
(JSC::DFG::PreciseLocalClobberizeAdaptor::def):
(JSC::DFG::PreciseLocalClobberizeAdaptor::callIfAppropriate):
(JSC::DFG::PreciseLocalClobberizeAdaptor::readTop):
(JSC::DFG::PreciseLocalClobberizeAdaptor::writeTop):
(JSC::DFG::forEachLocalReadByUnwind):
(JSC::DFG::preciseLocalClobberize):
* dfg/DFGPutLocalSinkingPhase.cpp: Added.
(JSC::DFG::performPutLocalSinking):
* dfg/DFGPutLocalSinkingPhase.h: Added.
* dfg/DFGSSACalculator.h:
(JSC::DFG::SSACalculator::computePhis):
* dfg/DFGValidate.cpp:
Source/WTF:
Make the set bits of a BitVector iterable.
* wtf/BitVector.h:
(WTF::BitVector::SetBitsIterable::SetBitsIterable):
(WTF::BitVector::SetBitsIterable::iterator::iterator):
(WTF::BitVector::SetBitsIterable::iterator::operator*):
(WTF::BitVector::SetBitsIterable::iterator::operator++):
(WTF::BitVector::SetBitsIterable::iterator::operator==):
(WTF::BitVector::SetBitsIterable::iterator::operator!=):
(WTF::BitVector::SetBitsIterable::begin):
(WTF::BitVector::SetBitsIterable::end):
(WTF::BitVector::setBits):
LayoutTests:
* js/regress/elidable-new-object-then-call-expected.txt: Added.
* js/regress/elidable-new-object-then-call.html: Added.
* js/regress/script-tests/elidable-new-object-then-call.js: Added.
(sumOfArithSeries):
(bar):
(foo):
Canonical link: https://commits.webkit.org/155232@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@174318 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2014-10-04 17:18:25 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
It should be possible to run liveness over registers without also tracking Tmps
https://bugs.webkit.org/show_bug.cgi?id=152963
Reviewed by Saam Barati.
Source/JavaScriptCore:
This adds a RegLivenessAdapter so that we can run Liveness over registers. This makes it
easier to write certain kinds of phases, like ReportUsedRegisters. I anticipate writing more
code like that for handling cold function calls. It also makes code like that somewhat more
scalable, since we're no longer using HashSets.
Currently, the way we track sets of registers is with a BitVector. Normally, we use the
RegisterSet class, which wraps BitVector, so that we can add()/contains() on Reg's. But in
the liveness analysis, everything gets turned into an index. So, we want to use BitVector
directly. To do that, I needed to make the BitVector API look a bit more like a set API. I
think that this is good, because the lack of set methods (add/remove/contains) has caused
bugs in the past. This makes BitVector have methods both for set operations on bits and array
operations on bits. I think that's good, since BitVector gets used in both contexts.
* b3/B3IndexSet.h:
(JSC::B3::IndexSet::Iterable::iterator::iterator):
(JSC::B3::IndexSet::Iterable::begin):
(JSC::B3::IndexSet::dump):
* b3/air/AirInstInlines.h:
(JSC::B3::Air::ForEach<Tmp>::forEach):
(JSC::B3::Air::ForEach<Arg>::forEach):
(JSC::B3::Air::ForEach<Reg>::forEach):
(JSC::B3::Air::Inst::forEach):
* b3/air/AirLiveness.h:
(JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter):
(JSC::B3::Air::RegLivenessAdapter::maxIndex):
(JSC::B3::Air::RegLivenessAdapter::acceptsType):
(JSC::B3::Air::RegLivenessAdapter::valueToIndex):
(JSC::B3::Air::RegLivenessAdapter::indexToValue):
* b3/air/AirReportUsedRegisters.cpp:
(JSC::B3::Air::reportUsedRegisters):
* jit/Reg.h:
(JSC::Reg::next):
(JSC::Reg::index):
(JSC::Reg::maxIndex):
(JSC::Reg::isSet):
(JSC::Reg::operator bool):
* jit/RegisterSet.h:
(JSC::RegisterSet::forEach):
Source/WTF:
Add set methods (add/contains/remove) to BitVector, since it gets used as a set in a lot of
places. This also makes BitVector a drop-in replacement for HashSet<unsigned> in a lot of
places.
Also made the iterator methods of BitVector live on BitVector directly rather than behind the
thing returned from setBits(). This makes sense since that makes BitVector even more of a
drop-in for HashSet. It's not harmful since we've never added any other mode of iterating a
BitVector other than this, so it doesn't make sense to make it harder to access.
* wtf/BitVector.h:
(WTF::BitVector::get):
(WTF::BitVector::contains):
(WTF::BitVector::set):
(WTF::BitVector::add):
(WTF::BitVector::ensureSizeAndSet):
(WTF::BitVector::clear):
(WTF::BitVector::remove):
(WTF::BitVector::hash):
(WTF::BitVector::iterator::iterator):
(WTF::BitVector::iterator::operator*):
(WTF::BitVector::iterator::operator++):
(WTF::BitVector::iterator::operator==):
(WTF::BitVector::iterator::operator!=):
(WTF::BitVector::begin):
(WTF::BitVector::end):
(WTF::BitVector::bitsInPointer):
(WTF::BitVector::SetBitsIterable::SetBitsIterable): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::iterator): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator*): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator++): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator==): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator!=): Deleted.
(WTF::BitVector::SetBitsIterable::begin): Deleted.
(WTF::BitVector::SetBitsIterable::end): Deleted.
(WTF::BitVector::setBits): Deleted.
Canonical link: https://commits.webkit.org/171043@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@194834 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-01-11 00:58:34 +00:00
|
|
|
iterator(const BitVector& bitVector, size_t index)
|
|
|
|
: m_bitVector(&bitVector)
|
|
|
|
, m_index(index)
|
|
|
|
{
|
|
|
|
}
|
FTL should sink PutLocals
https://bugs.webkit.org/show_bug.cgi?id=137168
Reviewed by Oliver Hunt.
Source/JavaScriptCore:
We've known for a while that our PutLocal situation was sub-optimal. We emit them anytime we
"pass" arguments to an inlined function call, because we need to enable the runtime to grab
those arguments when doing foo.arguments where foo is inlined: our engine doesn't deoptimize
in that case but rather just relies on the arguments being flushed (i.e. a copy of their
values is spilled) at a well-known place in a well-known format.
The PutLocals incur two costs: (1) they are store instructions and stores ain't free, and (2)
they look like escaping sites and so they inhibit object allocation sinking.
But in most cases, the PutLocals are unnecessary because the inlined code never performs any
side effect that could transitively lead to function.arguments. Even if the inlined code
could do such a side effect, it may be on a rare path so there is no need to penalize the
entire function.
This patch implements one solution to the PutLocal problem: it aggressively sinks PutLocals
to the latest possible point. This is even more aggressive than the object allocation
sinking. That sinking algorithm avoids creating situations where an object could be
materialized more than one along any path. PutLocal sinking, on the other hand, doesn't avoid
this at all - both to make the phase cheaper and simpler and to make it more aggressive.
Every PutLocal is sunk no matter what.
The upside of this patch is that it eliminates many PutLocals: many of them are sunk "past
their death", thus eliminating them completely. Others are sunk to rare paths. This enables a
lot of object allocation sinking and it removes a lot of pointless store instructions.
It also has downsites. Sinking PutLocals increases register pressure because it increases the
live ranges of things like inlined arguments.
This patch is a net performance win in its current form: 1% SunSpider regression, 2% OctaneV2
progression, 0.6% Kraken regression, 1% AsmBench progression, and 0.5% CompressionBench
regression. The biggest win is on Octane/raytrace, which improves by 27%.
Relanding after fixing internal builds. We have to be careful about implicit casts from int64
to int32.
* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.h:
* bytecode/Operands.h:
(JSC::Operands::dump): Deleted.
* bytecode/OperandsInlines.h:
(JSC::Traits>::dump):
* bytecode/VirtualRegister.h:
(JSC::VirtualRegister::isHeader):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
* dfg/DFGClobberSet.h:
(JSC::DFG::ClobberSetAdd::operator()):
(JSC::DFG::ClobberSetOverlaps::operator()):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
(JSC::DFG::NoOpClobberize::operator()):
(JSC::DFG::CheckClobberize::operator()):
(JSC::DFG::AbstractHeapOverlaps::operator()):
(JSC::DFG::ReadMethodClobberize::operator()):
(JSC::DFG::WriteMethodClobberize::operator()):
(JSC::DFG::DefMethodClobberize::operator()):
* dfg/DFGFlushFormat.h:
(JSC::DFG::merge):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::Graph):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::capturedVarsFor):
* dfg/DFGObjectAllocationSinkingPhase.cpp:
(JSC::DFG::ObjectAllocationSinkingPhase::determineMaterializationPoints):
(JSC::DFG::ObjectAllocationSinkingPhase::placeMaterializationPoints):
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
* dfg/DFGPreciseLocalClobberize.h: Added.
(JSC::DFG::PreciseLocalClobberizeAdaptor::PreciseLocalClobberizeAdaptor):
(JSC::DFG::PreciseLocalClobberizeAdaptor::read):
(JSC::DFG::PreciseLocalClobberizeAdaptor::write):
(JSC::DFG::PreciseLocalClobberizeAdaptor::def):
(JSC::DFG::PreciseLocalClobberizeAdaptor::callIfAppropriate):
(JSC::DFG::PreciseLocalClobberizeAdaptor::readTop):
(JSC::DFG::PreciseLocalClobberizeAdaptor::writeTop):
(JSC::DFG::forEachLocalReadByUnwind):
(JSC::DFG::preciseLocalClobberize):
* dfg/DFGPutLocalSinkingPhase.cpp: Added.
(JSC::DFG::performPutLocalSinking):
* dfg/DFGPutLocalSinkingPhase.h: Added.
* dfg/DFGSSACalculator.h:
(JSC::DFG::SSACalculator::computePhis):
* dfg/DFGValidate.cpp:
Source/WTF:
Make the set bits of a BitVector iterable.
* wtf/BitVector.h:
(WTF::BitVector::SetBitsIterable::SetBitsIterable):
(WTF::BitVector::SetBitsIterable::iterator::iterator):
(WTF::BitVector::SetBitsIterable::iterator::operator*):
(WTF::BitVector::SetBitsIterable::iterator::operator++):
(WTF::BitVector::SetBitsIterable::iterator::operator==):
(WTF::BitVector::SetBitsIterable::iterator::operator!=):
(WTF::BitVector::SetBitsIterable::begin):
(WTF::BitVector::SetBitsIterable::end):
(WTF::BitVector::setBits):
LayoutTests:
* js/regress/elidable-new-object-then-call-expected.txt: Added.
* js/regress/elidable-new-object-then-call.html: Added.
* js/regress/script-tests/elidable-new-object-then-call.js: Added.
(sumOfArithSeries):
(bar):
(foo):
Canonical link: https://commits.webkit.org/155232@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@174318 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2014-10-04 17:18:25 +00:00
|
|
|
|
It should be possible to run liveness over registers without also tracking Tmps
https://bugs.webkit.org/show_bug.cgi?id=152963
Reviewed by Saam Barati.
Source/JavaScriptCore:
This adds a RegLivenessAdapter so that we can run Liveness over registers. This makes it
easier to write certain kinds of phases, like ReportUsedRegisters. I anticipate writing more
code like that for handling cold function calls. It also makes code like that somewhat more
scalable, since we're no longer using HashSets.
Currently, the way we track sets of registers is with a BitVector. Normally, we use the
RegisterSet class, which wraps BitVector, so that we can add()/contains() on Reg's. But in
the liveness analysis, everything gets turned into an index. So, we want to use BitVector
directly. To do that, I needed to make the BitVector API look a bit more like a set API. I
think that this is good, because the lack of set methods (add/remove/contains) has caused
bugs in the past. This makes BitVector have methods both for set operations on bits and array
operations on bits. I think that's good, since BitVector gets used in both contexts.
* b3/B3IndexSet.h:
(JSC::B3::IndexSet::Iterable::iterator::iterator):
(JSC::B3::IndexSet::Iterable::begin):
(JSC::B3::IndexSet::dump):
* b3/air/AirInstInlines.h:
(JSC::B3::Air::ForEach<Tmp>::forEach):
(JSC::B3::Air::ForEach<Arg>::forEach):
(JSC::B3::Air::ForEach<Reg>::forEach):
(JSC::B3::Air::Inst::forEach):
* b3/air/AirLiveness.h:
(JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter):
(JSC::B3::Air::RegLivenessAdapter::maxIndex):
(JSC::B3::Air::RegLivenessAdapter::acceptsType):
(JSC::B3::Air::RegLivenessAdapter::valueToIndex):
(JSC::B3::Air::RegLivenessAdapter::indexToValue):
* b3/air/AirReportUsedRegisters.cpp:
(JSC::B3::Air::reportUsedRegisters):
* jit/Reg.h:
(JSC::Reg::next):
(JSC::Reg::index):
(JSC::Reg::maxIndex):
(JSC::Reg::isSet):
(JSC::Reg::operator bool):
* jit/RegisterSet.h:
(JSC::RegisterSet::forEach):
Source/WTF:
Add set methods (add/contains/remove) to BitVector, since it gets used as a set in a lot of
places. This also makes BitVector a drop-in replacement for HashSet<unsigned> in a lot of
places.
Also made the iterator methods of BitVector live on BitVector directly rather than behind the
thing returned from setBits(). This makes sense since that makes BitVector even more of a
drop-in for HashSet. It's not harmful since we've never added any other mode of iterating a
BitVector other than this, so it doesn't make sense to make it harder to access.
* wtf/BitVector.h:
(WTF::BitVector::get):
(WTF::BitVector::contains):
(WTF::BitVector::set):
(WTF::BitVector::add):
(WTF::BitVector::ensureSizeAndSet):
(WTF::BitVector::clear):
(WTF::BitVector::remove):
(WTF::BitVector::hash):
(WTF::BitVector::iterator::iterator):
(WTF::BitVector::iterator::operator*):
(WTF::BitVector::iterator::operator++):
(WTF::BitVector::iterator::operator==):
(WTF::BitVector::iterator::operator!=):
(WTF::BitVector::begin):
(WTF::BitVector::end):
(WTF::BitVector::bitsInPointer):
(WTF::BitVector::SetBitsIterable::SetBitsIterable): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::iterator): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator*): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator++): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator==): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator!=): Deleted.
(WTF::BitVector::SetBitsIterable::begin): Deleted.
(WTF::BitVector::SetBitsIterable::end): Deleted.
(WTF::BitVector::setBits): Deleted.
Canonical link: https://commits.webkit.org/171043@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@194834 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-01-11 00:58:34 +00:00
|
|
|
size_t operator*() const { return m_index; }
|
|
|
|
|
|
|
|
iterator& operator++()
|
|
|
|
{
|
|
|
|
m_index = m_bitVector->findBit(m_index + 1, true);
|
|
|
|
return *this;
|
|
|
|
}
|
2017-04-05 01:18:07 +00:00
|
|
|
|
GC constraint solving should be parallel
https://bugs.webkit.org/show_bug.cgi?id=179934
Reviewed by JF Bastien.
PerformanceTests:
Added a version of splay that measures latency in a way that run-jsc-benchmarks groks.
* Octane/splay.js: Added.
(this.Setup.setup.setup):
(this.TearDown.tearDown.tearDown):
(Benchmark):
(BenchmarkResult):
(BenchmarkResult.prototype.valueOf):
(BenchmarkSuite):
(alert):
(Math.random):
(BenchmarkSuite.ResetRNG):
(RunStep):
(BenchmarkSuite.RunSuites):
(BenchmarkSuite.CountBenchmarks):
(BenchmarkSuite.GeometricMean):
(BenchmarkSuite.GeometricMeanTime):
(BenchmarkSuite.AverageAbovePercentile):
(BenchmarkSuite.GeometricMeanLatency):
(BenchmarkSuite.FormatScore):
(BenchmarkSuite.prototype.NotifyStep):
(BenchmarkSuite.prototype.NotifyResult):
(BenchmarkSuite.prototype.NotifyError):
(BenchmarkSuite.prototype.RunSingleBenchmark):
(RunNextSetup):
(RunNextBenchmark):
(RunNextTearDown):
(BenchmarkSuite.prototype.RunStep):
(GeneratePayloadTree):
(GenerateKey):
(SplayUpdateStats):
(InsertNewNode):
(SplaySetup):
(SplayTearDown):
(SplayRun):
(SplayTree):
(SplayTree.prototype.isEmpty):
(SplayTree.prototype.insert):
(SplayTree.prototype.remove):
(SplayTree.prototype.find):
(SplayTree.prototype.findMax):
(SplayTree.prototype.findGreatestLessThan):
(SplayTree.prototype.exportKeys):
(SplayTree.prototype.splay_):
(SplayTree.Node):
(SplayTree.Node.prototype.traverse_):
(report):
(start):
Source/JavaScriptCore:
This makes it possible to do constraint solving in parallel. This looks like a 1% Speedometer
speed-up. It's more than 1% on trunk-Speedometer.
The constraint solver supports running constraints in parallel in two different ways:
- Run multiple constraints in parallel to each other. This only works for constraints that can
tolerate other constraints running concurrently to them (constraint.concurrency() ==
ConstraintConcurrency::Concurrent). This is the most basic kind of parallelism that the
constraint solver supports. All constraints except the JSC SPI constraints are concurrent. We
could probably make them concurrent, but I'm playing it safe for now.
- A constraint can create parallel work for itself, which the constraint solver will interleave
with other stuff. A constraint can report that it has parallel work by returning
ConstraintParallelism::Parallel from its executeImpl() function. Then the solver will allow that
constraint's doParallelWorkImpl() function to run on as many GC marker threads as are available,
for as long as that function wants to run.
It's not possible to have a non-concurrent constraint that creates parallel work.
The parallelism is implemented in terms of the existing GC marker threads. This turns out to be
most natural for two reasons:
- No need to start any other threads.
- The constraints all want to be passed a SlotVisitor. Running on the marker threads means having
access to those threads' SlotVisitors. Also, it means less load balancing. The solver will
create work on each marking thread's SlotVisitor. When the solver is done "stealing" a marker
thread, that thread will have work it can start doing immediately. Before this change, we had to
contribute the work found by the constraint solver to the global worklist so that it could be
distributed to the marker threads by load balancing. This change probably helps to avoid that
load balancing step.
A lot of this change is about making it easy to iterate GC data structures in parallel. This
change makes almost all constraints parallel-enabled, but only the DOM's output constraint uses
the parallel work API. That constraint iterates the marked cells in two subspaces. This change
makes it very easy to compose parallel iterators over subspaces, allocators, blocks, and cells.
The marked cell parallel iterator is composed out of parallel iterators for the others. A parallel
iterator is just an iterator that can do an atomic next() very quickly. We abstract them using
RefPtr<SharedTask<...()>>, where ... is the type returned from the iterator. We know it's done
when it returns a falsish version of ... (in the current code, that's always a pointer type, so
done is indicated by null).
* API/JSMarkingConstraintPrivate.cpp:
(JSContextGroupAddMarkingConstraint):
* API/JSVirtualMachine.mm:
(scanExternalObjectGraph):
(scanExternalRememberedSet):
* JavaScriptCore.xcodeproj/project.pbxproj:
* Sources.txt:
* bytecode/AccessCase.cpp:
(JSC::AccessCase::propagateTransitions const):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::visitWeakly):
(JSC::CodeBlock::shouldJettisonDueToOldAge):
(JSC::shouldMarkTransition):
(JSC::CodeBlock::propagateTransitions):
(JSC::CodeBlock::determineLiveness):
* dfg/DFGWorklist.cpp:
* ftl/FTLCompile.cpp:
(JSC::FTL::compile):
* heap/ConstraintParallelism.h: Added.
(WTF::printInternal):
* heap/Heap.cpp:
(JSC::Heap::Heap):
(JSC::Heap::addToRememberedSet):
(JSC::Heap::runFixpointPhase):
(JSC::Heap::stopThePeriphery):
(JSC::Heap::resumeThePeriphery):
(JSC::Heap::addCoreConstraints):
(JSC::Heap::setBonusVisitorTask):
(JSC::Heap::runTaskInParallel):
(JSC::Heap::forEachSlotVisitor): Deleted.
* heap/Heap.h:
(JSC::Heap::worldIsRunning const):
(JSC::Heap::runFunctionInParallel):
* heap/HeapInlines.h:
(JSC::Heap::worldIsStopped const):
(JSC::Heap::isMarked):
(JSC::Heap::incrementDeferralDepth):
(JSC::Heap::decrementDeferralDepth):
(JSC::Heap::decrementDeferralDepthAndGCIfNeeded):
(JSC::Heap::forEachSlotVisitor):
(JSC::Heap::collectorBelievesThatTheWorldIsStopped const): Deleted.
(JSC::Heap::isMarkedConcurrently): Deleted.
* heap/HeapSnapshotBuilder.cpp:
(JSC::HeapSnapshotBuilder::appendNode):
* heap/LargeAllocation.h:
(JSC::LargeAllocation::isMarked):
(JSC::LargeAllocation::isMarkedConcurrently): Deleted.
* heap/LockDuringMarking.h:
(JSC::lockDuringMarking):
* heap/MarkedAllocator.cpp:
(JSC::MarkedAllocator::parallelNotEmptyBlockSource):
* heap/MarkedAllocator.h:
* heap/MarkedBlock.h:
(JSC::MarkedBlock::aboutToMark):
(JSC::MarkedBlock::isMarked):
(JSC::MarkedBlock::areMarksStaleWithDependency): Deleted.
(JSC::MarkedBlock::isMarkedConcurrently): Deleted.
* heap/MarkedSpace.h:
(JSC::MarkedSpace::activeWeakSetsBegin):
(JSC::MarkedSpace::activeWeakSetsEnd):
(JSC::MarkedSpace::newActiveWeakSetsBegin):
(JSC::MarkedSpace::newActiveWeakSetsEnd):
* heap/MarkingConstraint.cpp:
(JSC::MarkingConstraint::MarkingConstraint):
(JSC::MarkingConstraint::execute):
(JSC::MarkingConstraint::quickWorkEstimate):
(JSC::MarkingConstraint::workEstimate):
(JSC::MarkingConstraint::doParallelWork):
(JSC::MarkingConstraint::finishParallelWork):
(JSC::MarkingConstraint::doParallelWorkImpl):
(JSC::MarkingConstraint::finishParallelWorkImpl):
* heap/MarkingConstraint.h:
(JSC::MarkingConstraint::lastExecuteParallelism const):
(JSC::MarkingConstraint::parallelism const):
(JSC::MarkingConstraint::quickWorkEstimate): Deleted.
(JSC::MarkingConstraint::workEstimate): Deleted.
* heap/MarkingConstraintSet.cpp:
(JSC::MarkingConstraintSet::MarkingConstraintSet):
(JSC::MarkingConstraintSet::add):
(JSC::MarkingConstraintSet::executeConvergence):
(JSC::MarkingConstraintSet::executeConvergenceImpl):
(JSC::MarkingConstraintSet::executeAll):
(JSC::MarkingConstraintSet::ExecutionContext::ExecutionContext): Deleted.
(JSC::MarkingConstraintSet::ExecutionContext::didVisitSomething const): Deleted.
(JSC::MarkingConstraintSet::ExecutionContext::shouldTimeOut const): Deleted.
(JSC::MarkingConstraintSet::ExecutionContext::drain): Deleted.
(JSC::MarkingConstraintSet::ExecutionContext::didExecute const): Deleted.
(JSC::MarkingConstraintSet::ExecutionContext::execute): Deleted.
(): Deleted.
* heap/MarkingConstraintSet.h:
* heap/MarkingConstraintSolver.cpp: Added.
(JSC::MarkingConstraintSolver::MarkingConstraintSolver):
(JSC::MarkingConstraintSolver::~MarkingConstraintSolver):
(JSC::MarkingConstraintSolver::didVisitSomething const):
(JSC::MarkingConstraintSolver::execute):
(JSC::MarkingConstraintSolver::drain):
(JSC::MarkingConstraintSolver::converge):
(JSC::MarkingConstraintSolver::runExecutionThread):
(JSC::MarkingConstraintSolver::didExecute):
* heap/MarkingConstraintSolver.h: Added.
* heap/OpaqueRootSet.h: Removed.
* heap/ParallelSourceAdapter.h: Added.
(JSC::ParallelSourceAdapter::ParallelSourceAdapter):
(JSC::createParallelSourceAdapter):
* heap/SimpleMarkingConstraint.cpp: Added.
(JSC::SimpleMarkingConstraint::SimpleMarkingConstraint):
(JSC::SimpleMarkingConstraint::~SimpleMarkingConstraint):
(JSC::SimpleMarkingConstraint::quickWorkEstimate):
(JSC::SimpleMarkingConstraint::executeImpl):
* heap/SimpleMarkingConstraint.h: Added.
* heap/SlotVisitor.cpp:
(JSC::SlotVisitor::didStartMarking):
(JSC::SlotVisitor::reset):
(JSC::SlotVisitor::appendToMarkStack):
(JSC::SlotVisitor::visitChildren):
(JSC::SlotVisitor::updateMutatorIsStopped):
(JSC::SlotVisitor::mutatorIsStoppedIsUpToDate const):
(JSC::SlotVisitor::drain):
(JSC::SlotVisitor::performIncrementOfDraining):
(JSC::SlotVisitor::didReachTermination):
(JSC::SlotVisitor::hasWork):
(JSC::SlotVisitor::drainFromShared):
(JSC::SlotVisitor::drainInParallelPassively):
(JSC::SlotVisitor::waitForTermination):
(JSC::SlotVisitor::addOpaqueRoot): Deleted.
(JSC::SlotVisitor::containsOpaqueRoot const): Deleted.
(JSC::SlotVisitor::containsOpaqueRootTriState const): Deleted.
(JSC::SlotVisitor::mergeIfNecessary): Deleted.
(JSC::SlotVisitor::mergeOpaqueRootsIfProfitable): Deleted.
(JSC::SlotVisitor::mergeOpaqueRoots): Deleted.
* heap/SlotVisitor.h:
* heap/SlotVisitorInlines.h:
(JSC::SlotVisitor::addOpaqueRoot):
(JSC::SlotVisitor::containsOpaqueRoot const):
(JSC::SlotVisitor::vm):
(JSC::SlotVisitor::vm const):
* heap/Subspace.cpp:
(JSC::Subspace::parallelAllocatorSource):
(JSC::Subspace::parallelNotEmptyMarkedBlockSource):
* heap/Subspace.h:
* heap/SubspaceInlines.h:
(JSC::Subspace::forEachMarkedCellInParallel):
* heap/VisitCounter.h: Added.
(JSC::VisitCounter::VisitCounter):
(JSC::VisitCounter::visitCount const):
* heap/VisitingTimeout.h: Removed.
* heap/WeakBlock.cpp:
(JSC::WeakBlock::specializedVisit):
* runtime/Structure.cpp:
(JSC::Structure::isCheapDuringGC):
(JSC::Structure::markIfCheap):
Source/WebCore:
No new tests because no change in behavior. This change is best tested using DOM-GC-intensive
benchmarks like Speedometer and Dromaeo.
This parallelizes the DOM's output constraint, and makes some small changes to make this more
scalable.
* ForwardingHeaders/heap/SimpleMarkingConstraint.h: Added.
* ForwardingHeaders/heap/VisitingTimeout.h: Removed.
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/DOMGCOutputConstraint.cpp: Added.
(WebCore::DOMGCOutputConstraint::DOMGCOutputConstraint):
(WebCore::DOMGCOutputConstraint::~DOMGCOutputConstraint):
(WebCore::DOMGCOutputConstraint::executeImpl):
(WebCore::DOMGCOutputConstraint::doParallelWorkImpl):
(WebCore::DOMGCOutputConstraint::finishParallelWorkImpl):
* bindings/js/DOMGCOutputConstraint.h: Added.
* bindings/js/WebCoreJSClientData.cpp:
(WebCore::JSVMClientData::initNormalWorld):
* dom/Node.cpp:
(WebCore::Node::eventTargetDataConcurrently):
(WebCore::Node::ensureEventTargetData):
(WebCore::Node::clearEventTargetData):
Source/WTF:
This does some changes to make it easier to do parallel constraint solving:
- I finally removed dependencyWith. This was a silly construct whose only purpose is to confuse
people about what it means to have a dependency chain. I took that as an opportunity to grealy
simplify the GC's use of dependency chaining.
- Added more logic to Deque<>, since I use it for part of the load balancer.
- Made it possible to profile lock contention. See
https://bugs.webkit.org/show_bug.cgi?id=180250#c0 for some preliminary measurements.
- Introduced holdLockIf, which makes it easy to perform predicated lock acquisition. We use that
to pick a lock in WebCore.
- Introduced CountingLock. It's like WTF::Lock except it also enables optimistic read transactions
sorta like Java's StampedLock.
* WTF.xcodeproj/project.pbxproj:
* wtf/Atomics.h:
(WTF::dependency):
(WTF::DependencyWith::DependencyWith): Deleted.
(WTF::dependencyWith): Deleted.
* wtf/BitVector.h:
(WTF::BitVector::iterator::operator++):
* wtf/CMakeLists.txt:
* wtf/ConcurrentPtrHashSet.cpp: Added.
(WTF::ConcurrentPtrHashSet::ConcurrentPtrHashSet):
(WTF::ConcurrentPtrHashSet::~ConcurrentPtrHashSet):
(WTF::ConcurrentPtrHashSet::deleteOldTables):
(WTF::ConcurrentPtrHashSet::clear):
(WTF::ConcurrentPtrHashSet::initialize):
(WTF::ConcurrentPtrHashSet::addSlow):
(WTF::ConcurrentPtrHashSet::resizeIfNecessary):
(WTF::ConcurrentPtrHashSet::resizeAndAdd):
(WTF::ConcurrentPtrHashSet::Table::create):
* wtf/ConcurrentPtrHashSet.h: Added.
(WTF::ConcurrentPtrHashSet::contains):
(WTF::ConcurrentPtrHashSet::add):
(WTF::ConcurrentPtrHashSet::size const):
(WTF::ConcurrentPtrHashSet::Table::maxLoad const):
(WTF::ConcurrentPtrHashSet::hash):
(WTF::ConcurrentPtrHashSet::cast):
(WTF::ConcurrentPtrHashSet::containsImpl const):
(WTF::ConcurrentPtrHashSet::addImpl):
* wtf/Deque.h:
(WTF::inlineCapacity>::takeFirst):
* wtf/FastMalloc.h:
* wtf/Lock.cpp:
(WTF::LockBase::lockSlow):
* wtf/Locker.h:
(WTF::holdLockIf):
* wtf/ScopedLambda.h:
* wtf/SharedTask.h:
(WTF::SharedTask<PassedResultType):
(WTF::SharedTask<ResultType): Deleted.
* wtf/StackShot.h: Added.
(WTF::StackShot::StackShot):
(WTF::StackShot::operator=):
(WTF::StackShot::array const):
(WTF::StackShot::size const):
(WTF::StackShot::operator bool const):
(WTF::StackShot::operator== const):
(WTF::StackShot::hash const):
(WTF::StackShot::isHashTableDeletedValue const):
(WTF::StackShot::operator> const):
(WTF::StackShot::deletedValueArray):
(WTF::StackShotHash::hash):
(WTF::StackShotHash::equal):
* wtf/StackShotProfiler.h: Added.
(WTF::StackShotProfiler::StackShotProfiler):
(WTF::StackShotProfiler::profile):
(WTF::StackShotProfiler::run):
Tools:
* Scripts/run-jsc-benchmarks: Add splay-latency test, since this change needed to be carefully validated with that benchmark.
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/ConcurrentPtrHashSet.cpp: Added. This has unit tests of the new concurrent data structure. The tests focus on correctness under serial execution, which appears to be enough for now (it's so easy to catch a concurrency bug by just running the GC).
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/196360@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@225524 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-12-05 17:53:57 +00:00
|
|
|
iterator operator++(int)
|
|
|
|
{
|
|
|
|
iterator result = *this;
|
|
|
|
++(*this);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-04-05 01:18:07 +00:00
|
|
|
bool isAtEnd() const
|
|
|
|
{
|
|
|
|
return m_index >= m_bitVector->size();
|
|
|
|
}
|
It should be possible to run liveness over registers without also tracking Tmps
https://bugs.webkit.org/show_bug.cgi?id=152963
Reviewed by Saam Barati.
Source/JavaScriptCore:
This adds a RegLivenessAdapter so that we can run Liveness over registers. This makes it
easier to write certain kinds of phases, like ReportUsedRegisters. I anticipate writing more
code like that for handling cold function calls. It also makes code like that somewhat more
scalable, since we're no longer using HashSets.
Currently, the way we track sets of registers is with a BitVector. Normally, we use the
RegisterSet class, which wraps BitVector, so that we can add()/contains() on Reg's. But in
the liveness analysis, everything gets turned into an index. So, we want to use BitVector
directly. To do that, I needed to make the BitVector API look a bit more like a set API. I
think that this is good, because the lack of set methods (add/remove/contains) has caused
bugs in the past. This makes BitVector have methods both for set operations on bits and array
operations on bits. I think that's good, since BitVector gets used in both contexts.
* b3/B3IndexSet.h:
(JSC::B3::IndexSet::Iterable::iterator::iterator):
(JSC::B3::IndexSet::Iterable::begin):
(JSC::B3::IndexSet::dump):
* b3/air/AirInstInlines.h:
(JSC::B3::Air::ForEach<Tmp>::forEach):
(JSC::B3::Air::ForEach<Arg>::forEach):
(JSC::B3::Air::ForEach<Reg>::forEach):
(JSC::B3::Air::Inst::forEach):
* b3/air/AirLiveness.h:
(JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter):
(JSC::B3::Air::RegLivenessAdapter::maxIndex):
(JSC::B3::Air::RegLivenessAdapter::acceptsType):
(JSC::B3::Air::RegLivenessAdapter::valueToIndex):
(JSC::B3::Air::RegLivenessAdapter::indexToValue):
* b3/air/AirReportUsedRegisters.cpp:
(JSC::B3::Air::reportUsedRegisters):
* jit/Reg.h:
(JSC::Reg::next):
(JSC::Reg::index):
(JSC::Reg::maxIndex):
(JSC::Reg::isSet):
(JSC::Reg::operator bool):
* jit/RegisterSet.h:
(JSC::RegisterSet::forEach):
Source/WTF:
Add set methods (add/contains/remove) to BitVector, since it gets used as a set in a lot of
places. This also makes BitVector a drop-in replacement for HashSet<unsigned> in a lot of
places.
Also made the iterator methods of BitVector live on BitVector directly rather than behind the
thing returned from setBits(). This makes sense since that makes BitVector even more of a
drop-in for HashSet. It's not harmful since we've never added any other mode of iterating a
BitVector other than this, so it doesn't make sense to make it harder to access.
* wtf/BitVector.h:
(WTF::BitVector::get):
(WTF::BitVector::contains):
(WTF::BitVector::set):
(WTF::BitVector::add):
(WTF::BitVector::ensureSizeAndSet):
(WTF::BitVector::clear):
(WTF::BitVector::remove):
(WTF::BitVector::hash):
(WTF::BitVector::iterator::iterator):
(WTF::BitVector::iterator::operator*):
(WTF::BitVector::iterator::operator++):
(WTF::BitVector::iterator::operator==):
(WTF::BitVector::iterator::operator!=):
(WTF::BitVector::begin):
(WTF::BitVector::end):
(WTF::BitVector::bitsInPointer):
(WTF::BitVector::SetBitsIterable::SetBitsIterable): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::iterator): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator*): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator++): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator==): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator!=): Deleted.
(WTF::BitVector::SetBitsIterable::begin): Deleted.
(WTF::BitVector::SetBitsIterable::end): Deleted.
(WTF::BitVector::setBits): Deleted.
Canonical link: https://commits.webkit.org/171043@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@194834 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-01-11 00:58:34 +00:00
|
|
|
|
|
|
|
bool operator==(const iterator& other) const
|
|
|
|
{
|
|
|
|
return m_index == other.m_index;
|
|
|
|
}
|
FTL should sink PutLocals
https://bugs.webkit.org/show_bug.cgi?id=137168
Reviewed by Oliver Hunt.
Source/JavaScriptCore:
We've known for a while that our PutLocal situation was sub-optimal. We emit them anytime we
"pass" arguments to an inlined function call, because we need to enable the runtime to grab
those arguments when doing foo.arguments where foo is inlined: our engine doesn't deoptimize
in that case but rather just relies on the arguments being flushed (i.e. a copy of their
values is spilled) at a well-known place in a well-known format.
The PutLocals incur two costs: (1) they are store instructions and stores ain't free, and (2)
they look like escaping sites and so they inhibit object allocation sinking.
But in most cases, the PutLocals are unnecessary because the inlined code never performs any
side effect that could transitively lead to function.arguments. Even if the inlined code
could do such a side effect, it may be on a rare path so there is no need to penalize the
entire function.
This patch implements one solution to the PutLocal problem: it aggressively sinks PutLocals
to the latest possible point. This is even more aggressive than the object allocation
sinking. That sinking algorithm avoids creating situations where an object could be
materialized more than one along any path. PutLocal sinking, on the other hand, doesn't avoid
this at all - both to make the phase cheaper and simpler and to make it more aggressive.
Every PutLocal is sunk no matter what.
The upside of this patch is that it eliminates many PutLocals: many of them are sunk "past
their death", thus eliminating them completely. Others are sunk to rare paths. This enables a
lot of object allocation sinking and it removes a lot of pointless store instructions.
It also has downsites. Sinking PutLocals increases register pressure because it increases the
live ranges of things like inlined arguments.
This patch is a net performance win in its current form: 1% SunSpider regression, 2% OctaneV2
progression, 0.6% Kraken regression, 1% AsmBench progression, and 0.5% CompressionBench
regression. The biggest win is on Octane/raytrace, which improves by 27%.
Relanding after fixing internal builds. We have to be careful about implicit casts from int64
to int32.
* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.h:
* bytecode/Operands.h:
(JSC::Operands::dump): Deleted.
* bytecode/OperandsInlines.h:
(JSC::Traits>::dump):
* bytecode/VirtualRegister.h:
(JSC::VirtualRegister::isHeader):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
* dfg/DFGClobberSet.h:
(JSC::DFG::ClobberSetAdd::operator()):
(JSC::DFG::ClobberSetOverlaps::operator()):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
(JSC::DFG::NoOpClobberize::operator()):
(JSC::DFG::CheckClobberize::operator()):
(JSC::DFG::AbstractHeapOverlaps::operator()):
(JSC::DFG::ReadMethodClobberize::operator()):
(JSC::DFG::WriteMethodClobberize::operator()):
(JSC::DFG::DefMethodClobberize::operator()):
* dfg/DFGFlushFormat.h:
(JSC::DFG::merge):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::Graph):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::capturedVarsFor):
* dfg/DFGObjectAllocationSinkingPhase.cpp:
(JSC::DFG::ObjectAllocationSinkingPhase::determineMaterializationPoints):
(JSC::DFG::ObjectAllocationSinkingPhase::placeMaterializationPoints):
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
* dfg/DFGPreciseLocalClobberize.h: Added.
(JSC::DFG::PreciseLocalClobberizeAdaptor::PreciseLocalClobberizeAdaptor):
(JSC::DFG::PreciseLocalClobberizeAdaptor::read):
(JSC::DFG::PreciseLocalClobberizeAdaptor::write):
(JSC::DFG::PreciseLocalClobberizeAdaptor::def):
(JSC::DFG::PreciseLocalClobberizeAdaptor::callIfAppropriate):
(JSC::DFG::PreciseLocalClobberizeAdaptor::readTop):
(JSC::DFG::PreciseLocalClobberizeAdaptor::writeTop):
(JSC::DFG::forEachLocalReadByUnwind):
(JSC::DFG::preciseLocalClobberize):
* dfg/DFGPutLocalSinkingPhase.cpp: Added.
(JSC::DFG::performPutLocalSinking):
* dfg/DFGPutLocalSinkingPhase.h: Added.
* dfg/DFGSSACalculator.h:
(JSC::DFG::SSACalculator::computePhis):
* dfg/DFGValidate.cpp:
Source/WTF:
Make the set bits of a BitVector iterable.
* wtf/BitVector.h:
(WTF::BitVector::SetBitsIterable::SetBitsIterable):
(WTF::BitVector::SetBitsIterable::iterator::iterator):
(WTF::BitVector::SetBitsIterable::iterator::operator*):
(WTF::BitVector::SetBitsIterable::iterator::operator++):
(WTF::BitVector::SetBitsIterable::iterator::operator==):
(WTF::BitVector::SetBitsIterable::iterator::operator!=):
(WTF::BitVector::SetBitsIterable::begin):
(WTF::BitVector::SetBitsIterable::end):
(WTF::BitVector::setBits):
LayoutTests:
* js/regress/elidable-new-object-then-call-expected.txt: Added.
* js/regress/elidable-new-object-then-call.html: Added.
* js/regress/script-tests/elidable-new-object-then-call.js: Added.
(sumOfArithSeries):
(bar):
(foo):
Canonical link: https://commits.webkit.org/155232@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@174318 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2014-10-04 17:18:25 +00:00
|
|
|
|
It should be possible to run liveness over registers without also tracking Tmps
https://bugs.webkit.org/show_bug.cgi?id=152963
Reviewed by Saam Barati.
Source/JavaScriptCore:
This adds a RegLivenessAdapter so that we can run Liveness over registers. This makes it
easier to write certain kinds of phases, like ReportUsedRegisters. I anticipate writing more
code like that for handling cold function calls. It also makes code like that somewhat more
scalable, since we're no longer using HashSets.
Currently, the way we track sets of registers is with a BitVector. Normally, we use the
RegisterSet class, which wraps BitVector, so that we can add()/contains() on Reg's. But in
the liveness analysis, everything gets turned into an index. So, we want to use BitVector
directly. To do that, I needed to make the BitVector API look a bit more like a set API. I
think that this is good, because the lack of set methods (add/remove/contains) has caused
bugs in the past. This makes BitVector have methods both for set operations on bits and array
operations on bits. I think that's good, since BitVector gets used in both contexts.
* b3/B3IndexSet.h:
(JSC::B3::IndexSet::Iterable::iterator::iterator):
(JSC::B3::IndexSet::Iterable::begin):
(JSC::B3::IndexSet::dump):
* b3/air/AirInstInlines.h:
(JSC::B3::Air::ForEach<Tmp>::forEach):
(JSC::B3::Air::ForEach<Arg>::forEach):
(JSC::B3::Air::ForEach<Reg>::forEach):
(JSC::B3::Air::Inst::forEach):
* b3/air/AirLiveness.h:
(JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter):
(JSC::B3::Air::RegLivenessAdapter::maxIndex):
(JSC::B3::Air::RegLivenessAdapter::acceptsType):
(JSC::B3::Air::RegLivenessAdapter::valueToIndex):
(JSC::B3::Air::RegLivenessAdapter::indexToValue):
* b3/air/AirReportUsedRegisters.cpp:
(JSC::B3::Air::reportUsedRegisters):
* jit/Reg.h:
(JSC::Reg::next):
(JSC::Reg::index):
(JSC::Reg::maxIndex):
(JSC::Reg::isSet):
(JSC::Reg::operator bool):
* jit/RegisterSet.h:
(JSC::RegisterSet::forEach):
Source/WTF:
Add set methods (add/contains/remove) to BitVector, since it gets used as a set in a lot of
places. This also makes BitVector a drop-in replacement for HashSet<unsigned> in a lot of
places.
Also made the iterator methods of BitVector live on BitVector directly rather than behind the
thing returned from setBits(). This makes sense since that makes BitVector even more of a
drop-in for HashSet. It's not harmful since we've never added any other mode of iterating a
BitVector other than this, so it doesn't make sense to make it harder to access.
* wtf/BitVector.h:
(WTF::BitVector::get):
(WTF::BitVector::contains):
(WTF::BitVector::set):
(WTF::BitVector::add):
(WTF::BitVector::ensureSizeAndSet):
(WTF::BitVector::clear):
(WTF::BitVector::remove):
(WTF::BitVector::hash):
(WTF::BitVector::iterator::iterator):
(WTF::BitVector::iterator::operator*):
(WTF::BitVector::iterator::operator++):
(WTF::BitVector::iterator::operator==):
(WTF::BitVector::iterator::operator!=):
(WTF::BitVector::begin):
(WTF::BitVector::end):
(WTF::BitVector::bitsInPointer):
(WTF::BitVector::SetBitsIterable::SetBitsIterable): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::iterator): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator*): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator++): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator==): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator!=): Deleted.
(WTF::BitVector::SetBitsIterable::begin): Deleted.
(WTF::BitVector::SetBitsIterable::end): Deleted.
(WTF::BitVector::setBits): Deleted.
Canonical link: https://commits.webkit.org/171043@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@194834 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-01-11 00:58:34 +00:00
|
|
|
bool operator!=(const iterator& other) const
|
|
|
|
{
|
|
|
|
return !(*this == other);
|
|
|
|
}
|
FTL should sink PutLocals
https://bugs.webkit.org/show_bug.cgi?id=137168
Reviewed by Oliver Hunt.
Source/JavaScriptCore:
We've known for a while that our PutLocal situation was sub-optimal. We emit them anytime we
"pass" arguments to an inlined function call, because we need to enable the runtime to grab
those arguments when doing foo.arguments where foo is inlined: our engine doesn't deoptimize
in that case but rather just relies on the arguments being flushed (i.e. a copy of their
values is spilled) at a well-known place in a well-known format.
The PutLocals incur two costs: (1) they are store instructions and stores ain't free, and (2)
they look like escaping sites and so they inhibit object allocation sinking.
But in most cases, the PutLocals are unnecessary because the inlined code never performs any
side effect that could transitively lead to function.arguments. Even if the inlined code
could do such a side effect, it may be on a rare path so there is no need to penalize the
entire function.
This patch implements one solution to the PutLocal problem: it aggressively sinks PutLocals
to the latest possible point. This is even more aggressive than the object allocation
sinking. That sinking algorithm avoids creating situations where an object could be
materialized more than one along any path. PutLocal sinking, on the other hand, doesn't avoid
this at all - both to make the phase cheaper and simpler and to make it more aggressive.
Every PutLocal is sunk no matter what.
The upside of this patch is that it eliminates many PutLocals: many of them are sunk "past
their death", thus eliminating them completely. Others are sunk to rare paths. This enables a
lot of object allocation sinking and it removes a lot of pointless store instructions.
It also has downsites. Sinking PutLocals increases register pressure because it increases the
live ranges of things like inlined arguments.
This patch is a net performance win in its current form: 1% SunSpider regression, 2% OctaneV2
progression, 0.6% Kraken regression, 1% AsmBench progression, and 0.5% CompressionBench
regression. The biggest win is on Octane/raytrace, which improves by 27%.
Relanding after fixing internal builds. We have to be careful about implicit casts from int64
to int32.
* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.h:
* bytecode/Operands.h:
(JSC::Operands::dump): Deleted.
* bytecode/OperandsInlines.h:
(JSC::Traits>::dump):
* bytecode/VirtualRegister.h:
(JSC::VirtualRegister::isHeader):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
* dfg/DFGClobberSet.h:
(JSC::DFG::ClobberSetAdd::operator()):
(JSC::DFG::ClobberSetOverlaps::operator()):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
(JSC::DFG::NoOpClobberize::operator()):
(JSC::DFG::CheckClobberize::operator()):
(JSC::DFG::AbstractHeapOverlaps::operator()):
(JSC::DFG::ReadMethodClobberize::operator()):
(JSC::DFG::WriteMethodClobberize::operator()):
(JSC::DFG::DefMethodClobberize::operator()):
* dfg/DFGFlushFormat.h:
(JSC::DFG::merge):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::Graph):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::capturedVarsFor):
* dfg/DFGObjectAllocationSinkingPhase.cpp:
(JSC::DFG::ObjectAllocationSinkingPhase::determineMaterializationPoints):
(JSC::DFG::ObjectAllocationSinkingPhase::placeMaterializationPoints):
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
* dfg/DFGPreciseLocalClobberize.h: Added.
(JSC::DFG::PreciseLocalClobberizeAdaptor::PreciseLocalClobberizeAdaptor):
(JSC::DFG::PreciseLocalClobberizeAdaptor::read):
(JSC::DFG::PreciseLocalClobberizeAdaptor::write):
(JSC::DFG::PreciseLocalClobberizeAdaptor::def):
(JSC::DFG::PreciseLocalClobberizeAdaptor::callIfAppropriate):
(JSC::DFG::PreciseLocalClobberizeAdaptor::readTop):
(JSC::DFG::PreciseLocalClobberizeAdaptor::writeTop):
(JSC::DFG::forEachLocalReadByUnwind):
(JSC::DFG::preciseLocalClobberize):
* dfg/DFGPutLocalSinkingPhase.cpp: Added.
(JSC::DFG::performPutLocalSinking):
* dfg/DFGPutLocalSinkingPhase.h: Added.
* dfg/DFGSSACalculator.h:
(JSC::DFG::SSACalculator::computePhis):
* dfg/DFGValidate.cpp:
Source/WTF:
Make the set bits of a BitVector iterable.
* wtf/BitVector.h:
(WTF::BitVector::SetBitsIterable::SetBitsIterable):
(WTF::BitVector::SetBitsIterable::iterator::iterator):
(WTF::BitVector::SetBitsIterable::iterator::operator*):
(WTF::BitVector::SetBitsIterable::iterator::operator++):
(WTF::BitVector::SetBitsIterable::iterator::operator==):
(WTF::BitVector::SetBitsIterable::iterator::operator!=):
(WTF::BitVector::SetBitsIterable::begin):
(WTF::BitVector::SetBitsIterable::end):
(WTF::BitVector::setBits):
LayoutTests:
* js/regress/elidable-new-object-then-call-expected.txt: Added.
* js/regress/elidable-new-object-then-call.html: Added.
* js/regress/script-tests/elidable-new-object-then-call.js: Added.
(sumOfArithSeries):
(bar):
(foo):
Canonical link: https://commits.webkit.org/155232@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@174318 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2014-10-04 17:18:25 +00:00
|
|
|
private:
|
It should be possible to run liveness over registers without also tracking Tmps
https://bugs.webkit.org/show_bug.cgi?id=152963
Reviewed by Saam Barati.
Source/JavaScriptCore:
This adds a RegLivenessAdapter so that we can run Liveness over registers. This makes it
easier to write certain kinds of phases, like ReportUsedRegisters. I anticipate writing more
code like that for handling cold function calls. It also makes code like that somewhat more
scalable, since we're no longer using HashSets.
Currently, the way we track sets of registers is with a BitVector. Normally, we use the
RegisterSet class, which wraps BitVector, so that we can add()/contains() on Reg's. But in
the liveness analysis, everything gets turned into an index. So, we want to use BitVector
directly. To do that, I needed to make the BitVector API look a bit more like a set API. I
think that this is good, because the lack of set methods (add/remove/contains) has caused
bugs in the past. This makes BitVector have methods both for set operations on bits and array
operations on bits. I think that's good, since BitVector gets used in both contexts.
* b3/B3IndexSet.h:
(JSC::B3::IndexSet::Iterable::iterator::iterator):
(JSC::B3::IndexSet::Iterable::begin):
(JSC::B3::IndexSet::dump):
* b3/air/AirInstInlines.h:
(JSC::B3::Air::ForEach<Tmp>::forEach):
(JSC::B3::Air::ForEach<Arg>::forEach):
(JSC::B3::Air::ForEach<Reg>::forEach):
(JSC::B3::Air::Inst::forEach):
* b3/air/AirLiveness.h:
(JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter):
(JSC::B3::Air::RegLivenessAdapter::maxIndex):
(JSC::B3::Air::RegLivenessAdapter::acceptsType):
(JSC::B3::Air::RegLivenessAdapter::valueToIndex):
(JSC::B3::Air::RegLivenessAdapter::indexToValue):
* b3/air/AirReportUsedRegisters.cpp:
(JSC::B3::Air::reportUsedRegisters):
* jit/Reg.h:
(JSC::Reg::next):
(JSC::Reg::index):
(JSC::Reg::maxIndex):
(JSC::Reg::isSet):
(JSC::Reg::operator bool):
* jit/RegisterSet.h:
(JSC::RegisterSet::forEach):
Source/WTF:
Add set methods (add/contains/remove) to BitVector, since it gets used as a set in a lot of
places. This also makes BitVector a drop-in replacement for HashSet<unsigned> in a lot of
places.
Also made the iterator methods of BitVector live on BitVector directly rather than behind the
thing returned from setBits(). This makes sense since that makes BitVector even more of a
drop-in for HashSet. It's not harmful since we've never added any other mode of iterating a
BitVector other than this, so it doesn't make sense to make it harder to access.
* wtf/BitVector.h:
(WTF::BitVector::get):
(WTF::BitVector::contains):
(WTF::BitVector::set):
(WTF::BitVector::add):
(WTF::BitVector::ensureSizeAndSet):
(WTF::BitVector::clear):
(WTF::BitVector::remove):
(WTF::BitVector::hash):
(WTF::BitVector::iterator::iterator):
(WTF::BitVector::iterator::operator*):
(WTF::BitVector::iterator::operator++):
(WTF::BitVector::iterator::operator==):
(WTF::BitVector::iterator::operator!=):
(WTF::BitVector::begin):
(WTF::BitVector::end):
(WTF::BitVector::bitsInPointer):
(WTF::BitVector::SetBitsIterable::SetBitsIterable): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::iterator): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator*): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator++): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator==): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator!=): Deleted.
(WTF::BitVector::SetBitsIterable::begin): Deleted.
(WTF::BitVector::SetBitsIterable::end): Deleted.
(WTF::BitVector::setBits): Deleted.
Canonical link: https://commits.webkit.org/171043@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@194834 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-01-11 00:58:34 +00:00
|
|
|
const BitVector* m_bitVector;
|
|
|
|
size_t m_index;
|
FTL should sink PutLocals
https://bugs.webkit.org/show_bug.cgi?id=137168
Reviewed by Oliver Hunt.
Source/JavaScriptCore:
We've known for a while that our PutLocal situation was sub-optimal. We emit them anytime we
"pass" arguments to an inlined function call, because we need to enable the runtime to grab
those arguments when doing foo.arguments where foo is inlined: our engine doesn't deoptimize
in that case but rather just relies on the arguments being flushed (i.e. a copy of their
values is spilled) at a well-known place in a well-known format.
The PutLocals incur two costs: (1) they are store instructions and stores ain't free, and (2)
they look like escaping sites and so they inhibit object allocation sinking.
But in most cases, the PutLocals are unnecessary because the inlined code never performs any
side effect that could transitively lead to function.arguments. Even if the inlined code
could do such a side effect, it may be on a rare path so there is no need to penalize the
entire function.
This patch implements one solution to the PutLocal problem: it aggressively sinks PutLocals
to the latest possible point. This is even more aggressive than the object allocation
sinking. That sinking algorithm avoids creating situations where an object could be
materialized more than one along any path. PutLocal sinking, on the other hand, doesn't avoid
this at all - both to make the phase cheaper and simpler and to make it more aggressive.
Every PutLocal is sunk no matter what.
The upside of this patch is that it eliminates many PutLocals: many of them are sunk "past
their death", thus eliminating them completely. Others are sunk to rare paths. This enables a
lot of object allocation sinking and it removes a lot of pointless store instructions.
It also has downsites. Sinking PutLocals increases register pressure because it increases the
live ranges of things like inlined arguments.
This patch is a net performance win in its current form: 1% SunSpider regression, 2% OctaneV2
progression, 0.6% Kraken regression, 1% AsmBench progression, and 0.5% CompressionBench
regression. The biggest win is on Octane/raytrace, which improves by 27%.
Relanding after fixing internal builds. We have to be careful about implicit casts from int64
to int32.
* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.h:
* bytecode/Operands.h:
(JSC::Operands::dump): Deleted.
* bytecode/OperandsInlines.h:
(JSC::Traits>::dump):
* bytecode/VirtualRegister.h:
(JSC::VirtualRegister::isHeader):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
* dfg/DFGClobberSet.h:
(JSC::DFG::ClobberSetAdd::operator()):
(JSC::DFG::ClobberSetOverlaps::operator()):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
(JSC::DFG::NoOpClobberize::operator()):
(JSC::DFG::CheckClobberize::operator()):
(JSC::DFG::AbstractHeapOverlaps::operator()):
(JSC::DFG::ReadMethodClobberize::operator()):
(JSC::DFG::WriteMethodClobberize::operator()):
(JSC::DFG::DefMethodClobberize::operator()):
* dfg/DFGFlushFormat.h:
(JSC::DFG::merge):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::Graph):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::capturedVarsFor):
* dfg/DFGObjectAllocationSinkingPhase.cpp:
(JSC::DFG::ObjectAllocationSinkingPhase::determineMaterializationPoints):
(JSC::DFG::ObjectAllocationSinkingPhase::placeMaterializationPoints):
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
* dfg/DFGPreciseLocalClobberize.h: Added.
(JSC::DFG::PreciseLocalClobberizeAdaptor::PreciseLocalClobberizeAdaptor):
(JSC::DFG::PreciseLocalClobberizeAdaptor::read):
(JSC::DFG::PreciseLocalClobberizeAdaptor::write):
(JSC::DFG::PreciseLocalClobberizeAdaptor::def):
(JSC::DFG::PreciseLocalClobberizeAdaptor::callIfAppropriate):
(JSC::DFG::PreciseLocalClobberizeAdaptor::readTop):
(JSC::DFG::PreciseLocalClobberizeAdaptor::writeTop):
(JSC::DFG::forEachLocalReadByUnwind):
(JSC::DFG::preciseLocalClobberize):
* dfg/DFGPutLocalSinkingPhase.cpp: Added.
(JSC::DFG::performPutLocalSinking):
* dfg/DFGPutLocalSinkingPhase.h: Added.
* dfg/DFGSSACalculator.h:
(JSC::DFG::SSACalculator::computePhis):
* dfg/DFGValidate.cpp:
Source/WTF:
Make the set bits of a BitVector iterable.
* wtf/BitVector.h:
(WTF::BitVector::SetBitsIterable::SetBitsIterable):
(WTF::BitVector::SetBitsIterable::iterator::iterator):
(WTF::BitVector::SetBitsIterable::iterator::operator*):
(WTF::BitVector::SetBitsIterable::iterator::operator++):
(WTF::BitVector::SetBitsIterable::iterator::operator==):
(WTF::BitVector::SetBitsIterable::iterator::operator!=):
(WTF::BitVector::SetBitsIterable::begin):
(WTF::BitVector::SetBitsIterable::end):
(WTF::BitVector::setBits):
LayoutTests:
* js/regress/elidable-new-object-then-call-expected.txt: Added.
* js/regress/elidable-new-object-then-call.html: Added.
* js/regress/script-tests/elidable-new-object-then-call.js: Added.
(sumOfArithSeries):
(bar):
(foo):
Canonical link: https://commits.webkit.org/155232@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@174318 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2014-10-04 17:18:25 +00:00
|
|
|
};
|
It should be possible to run liveness over registers without also tracking Tmps
https://bugs.webkit.org/show_bug.cgi?id=152963
Reviewed by Saam Barati.
Source/JavaScriptCore:
This adds a RegLivenessAdapter so that we can run Liveness over registers. This makes it
easier to write certain kinds of phases, like ReportUsedRegisters. I anticipate writing more
code like that for handling cold function calls. It also makes code like that somewhat more
scalable, since we're no longer using HashSets.
Currently, the way we track sets of registers is with a BitVector. Normally, we use the
RegisterSet class, which wraps BitVector, so that we can add()/contains() on Reg's. But in
the liveness analysis, everything gets turned into an index. So, we want to use BitVector
directly. To do that, I needed to make the BitVector API look a bit more like a set API. I
think that this is good, because the lack of set methods (add/remove/contains) has caused
bugs in the past. This makes BitVector have methods both for set operations on bits and array
operations on bits. I think that's good, since BitVector gets used in both contexts.
* b3/B3IndexSet.h:
(JSC::B3::IndexSet::Iterable::iterator::iterator):
(JSC::B3::IndexSet::Iterable::begin):
(JSC::B3::IndexSet::dump):
* b3/air/AirInstInlines.h:
(JSC::B3::Air::ForEach<Tmp>::forEach):
(JSC::B3::Air::ForEach<Arg>::forEach):
(JSC::B3::Air::ForEach<Reg>::forEach):
(JSC::B3::Air::Inst::forEach):
* b3/air/AirLiveness.h:
(JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter):
(JSC::B3::Air::RegLivenessAdapter::maxIndex):
(JSC::B3::Air::RegLivenessAdapter::acceptsType):
(JSC::B3::Air::RegLivenessAdapter::valueToIndex):
(JSC::B3::Air::RegLivenessAdapter::indexToValue):
* b3/air/AirReportUsedRegisters.cpp:
(JSC::B3::Air::reportUsedRegisters):
* jit/Reg.h:
(JSC::Reg::next):
(JSC::Reg::index):
(JSC::Reg::maxIndex):
(JSC::Reg::isSet):
(JSC::Reg::operator bool):
* jit/RegisterSet.h:
(JSC::RegisterSet::forEach):
Source/WTF:
Add set methods (add/contains/remove) to BitVector, since it gets used as a set in a lot of
places. This also makes BitVector a drop-in replacement for HashSet<unsigned> in a lot of
places.
Also made the iterator methods of BitVector live on BitVector directly rather than behind the
thing returned from setBits(). This makes sense since that makes BitVector even more of a
drop-in for HashSet. It's not harmful since we've never added any other mode of iterating a
BitVector other than this, so it doesn't make sense to make it harder to access.
* wtf/BitVector.h:
(WTF::BitVector::get):
(WTF::BitVector::contains):
(WTF::BitVector::set):
(WTF::BitVector::add):
(WTF::BitVector::ensureSizeAndSet):
(WTF::BitVector::clear):
(WTF::BitVector::remove):
(WTF::BitVector::hash):
(WTF::BitVector::iterator::iterator):
(WTF::BitVector::iterator::operator*):
(WTF::BitVector::iterator::operator++):
(WTF::BitVector::iterator::operator==):
(WTF::BitVector::iterator::operator!=):
(WTF::BitVector::begin):
(WTF::BitVector::end):
(WTF::BitVector::bitsInPointer):
(WTF::BitVector::SetBitsIterable::SetBitsIterable): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::iterator): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator*): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator++): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator==): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator!=): Deleted.
(WTF::BitVector::SetBitsIterable::begin): Deleted.
(WTF::BitVector::SetBitsIterable::end): Deleted.
(WTF::BitVector::setBits): Deleted.
Canonical link: https://commits.webkit.org/171043@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@194834 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-01-11 00:58:34 +00:00
|
|
|
|
|
|
|
// Use this to iterate over set bits.
|
|
|
|
iterator begin() const { return iterator(*this, findBit(0, true)); }
|
|
|
|
iterator end() const { return iterator(*this, size()); }
|
Make AirAllocateRegistersByGraphColoring use less memory
https://bugs.webkit.org/show_bug.cgi?id=225848
Reviewed by Filip Pizlo.
Source/JavaScriptCore:
We've had some jetsam problems caused by the main Air register allocator, which caused us to lower Options::maximumTmpsForGraphColoring.
Hence this patch tries to improve the memory usage of the allocator. It includes several changes:
- Change the datastructure used for representing the interference graph. Before it was effectively a HashSet<std::pair<uint16_t, uint16_t>. Now, it is either a Bitvector (for n < 400 for now, can be tweaked easily), or a Vector<LikelyDenseUnsignedIntegerSet<uint16_t>> otherwise.
LikelyDenseUnsignedIntegerSet is a new datastructure introduced by this patch, it is either a HashSet if very sparse, or a BitVector + an amount to shift it by.
This is by far the largest memory reduction in this patch, it reduces the maximum memory used for an interference graph in tsf-wasm in JetStream2 from 16MB to 700kB, and in mruby-wasm.aotoki.dev from 262MB to 20MB (the later only happen when we increase Options::maximumTmpsForGraphColoring.. this is the exact function which caused us to lower it).
Its effect on smaller functions in JetStream2 is rarely as dramatic but always an improvement, and improvements between 2x and 5x are extremely common (10x to 30x are significantly rarer but do occur).
- In order to easily test this change and any further change to this datastructure, the old approach was preserved as InterferenceHashSet, and a template to run two such datastructures in parallel, checking their equivalence was added: InstrumentedInterferenceGraph. Running with it and reportInterferenceGraphMemoryUse set to true was used to compute the numbers given above.
- There was already some template parameter to change the size of the tmp indices from unsigned to uint16_t but the code failed to compile unless it was unsigned. I fixed this, made more consistent use of it, and switched to uint16_t in the very common case that we have less than 65k Tmps (we can have more despite the option because of spilling). This halved the memory usage of various other datastructures in the register allocator
- unspillableTmps was a HashSet<unsigned>. Since it is often quite dense (often around 20% on JetStream2), I replaced it by a Bitvector instead
- m_biases was a HashMap<IndexType, HashSet<IndexType>>. Since it is extremely rare that the sets have more than 8 elements (from looking at some instrumented run of JetStream2), I replaced it by HashMap<IndexType, SmallSet<IndexType>>. This not only significantly reduces memory, but nearly halves the time spent in assignColors(around 80ms -> 40ms in JetStream 2)
- UseCounts was needlessly general: it is only used by the register allocator (all other references to UseCounts refer to the completely different B3::UseCounts), so there is no point in it computing, and then storing lots of irrelevant data. A float is also more than enough precision (especially since it is pretty much always 1, 10, 100, or 1000 in practice…). Also, since we only need it indexed by Tmps, we can use a Vector with AbsoluteTmpMapper instead of its HashMap. These changes are not just memory savings, they also make selectSpill way faster (570ms -> 250ms on my machine on JetStream2)
- While I was at it, I did a couple of other tweaks to the logic of selectSpill. In particular, instead of having to check for isFastTmp every time, I just put the fast tmps directly in unspillableTmps, which prevents them from getting added to m_spillWorklist in the first place. This + a bit of clean-up (for example putting an early exit instead of setting score to infinity in the case of dead tmps) resulted in a further perf win (to roughly 200ms spent in selectSpill() on JetStream2)
All together, this patch reduces the time spent in the register allocator by roughly 15 to 20% in JetStream2 (tested both with the Briggs and the IRC allocators on my MBP 2019).
I do not yet have precise performance numbers for this exact patch, but benchmarking a previous version of it (with a less optimized interference graph) resulted in significant RAMification improvements (around 1%), and more surprisingly some JetStream2 improvements on weaker machines (e.g. an iPhone 7 gained > 1%). I believe these gains come either from less trashing of the caches, or less contention caused by the memory traffic.
I will try to update the bugzilla with more up-to-date thorough results when I get them.
This patch does not increase Options::maximumTmpsForGraphColoring, I intend to do that in a separate patch to make it easier to revert in case of a problem.
* b3/B3ReduceLoopStrength.cpp:
(JSC::B3::ReduceLoopStrength::reduceByteCopyLoopsToMemcpy):
* b3/air/AirAllocateRegistersAndStackByLinearScan.cpp:
* b3/air/AirAllocateRegistersByGraphColoring.cpp:
(JSC::B3::Air::allocateRegistersByGraphColoring):
* b3/air/AirCode.h:
(JSC::B3::Air::Code::forEachFastTmp const):
* b3/air/AirUseCounts.h:
(JSC::B3::Air::UseCounts::UseCounts):
(JSC::B3::Air::UseCounts::isConstDef const):
(JSC::B3::Air::UseCounts::numWarmUsesAndDefs const):
(JSC::B3::Air::UseCounts::dump const):
* parser/Nodes.h:
Source/WTF:
Two changes: the addition of LikelyDenseUnsignedIntegerSet, and various improvements to Small(Ptr)Set.
The latter include:
- Renaming SmallPtrSet into SmallSet, as it now supports integers as well as pointers.
- Reducing its size by sharing the same storage for m_buffer and for m_smallStorage.
This is safe to do, because all operations branch on isSmall() which depends purely on m_capacity.
- Adding trivial size(), isEmpty() and memoryUse() methods
- Adding a comment at the top of the file explaining when to use, and (more importantly) not to use SmallSet.
LikelyDenseUnsignedIntegerSet is an even more specialized data structure, that can represent sets of unsigned integers very compactly if they are clustered.
Finally I added an outOfLineMemoryUse() method to BitVector, making it more convenient to compare the memory consumption of different data structures in the register allocator.
* WTF.xcodeproj/project.pbxproj:
* wtf/BitVector.h:
* wtf/CMakeLists.txt:
* wtf/LikelyDenseUnsignedIntegerSet.cpp: Copied from Source/WTF/wtf/SmallPtrSet.cpp.
* wtf/LikelyDenseUnsignedIntegerSet.h: Added.
(WTF::LikelyDenseUnsignedIntegerSet::LikelyDenseUnsignedIntegerSet):
(WTF::LikelyDenseUnsignedIntegerSet::~LikelyDenseUnsignedIntegerSet):
(WTF::LikelyDenseUnsignedIntegerSet::contains const):
(WTF::LikelyDenseUnsignedIntegerSet::add):
(WTF::LikelyDenseUnsignedIntegerSet::size const):
(WTF::LikelyDenseUnsignedIntegerSet::iterator::iterator):
(WTF::LikelyDenseUnsignedIntegerSet::iterator::m_shift):
(WTF::LikelyDenseUnsignedIntegerSet::iterator::operator++):
(WTF::LikelyDenseUnsignedIntegerSet::iterator::operator* const):
(WTF::LikelyDenseUnsignedIntegerSet::iterator::operator== const):
(WTF::LikelyDenseUnsignedIntegerSet::iterator::operator!= const):
(WTF::LikelyDenseUnsignedIntegerSet::begin const):
(WTF::LikelyDenseUnsignedIntegerSet::end const):
(WTF::LikelyDenseUnsignedIntegerSet::memoryUse const):
(WTF::LikelyDenseUnsignedIntegerSet::validate const):
(WTF::LikelyDenseUnsignedIntegerSet::isBitVector const):
(WTF::LikelyDenseUnsignedIntegerSet::isValidValue const):
(WTF::LikelyDenseUnsignedIntegerSet::transitionToHashSet):
(WTF::LikelyDenseUnsignedIntegerSet::transitionToBitVector):
* wtf/SmallPtrSet.h: Removed.
* wtf/SmallSet.cpp: Renamed from Source/WTF/wtf/SmallPtrSet.cpp.
* wtf/SmallSet.h: Added.
Tools:
Simply added some tests for SmallSet.
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/SmallSet.cpp: Added.
(TestWebKitAPI::testSmallSetOfUnsigned):
(TestWebKitAPI::testSmallSetOfPointers):
(TestWebKitAPI::testVectorsOfSmallSetsOfUnsigned):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/237893@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@277714 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-05-19 03:24:14 +00:00
|
|
|
|
|
|
|
unsigned outOfLineMemoryUse() const
|
|
|
|
{
|
|
|
|
if (isInline())
|
|
|
|
return 0;
|
|
|
|
return byteCount(size());
|
|
|
|
}
|
It should be possible to run liveness over registers without also tracking Tmps
https://bugs.webkit.org/show_bug.cgi?id=152963
Reviewed by Saam Barati.
Source/JavaScriptCore:
This adds a RegLivenessAdapter so that we can run Liveness over registers. This makes it
easier to write certain kinds of phases, like ReportUsedRegisters. I anticipate writing more
code like that for handling cold function calls. It also makes code like that somewhat more
scalable, since we're no longer using HashSets.
Currently, the way we track sets of registers is with a BitVector. Normally, we use the
RegisterSet class, which wraps BitVector, so that we can add()/contains() on Reg's. But in
the liveness analysis, everything gets turned into an index. So, we want to use BitVector
directly. To do that, I needed to make the BitVector API look a bit more like a set API. I
think that this is good, because the lack of set methods (add/remove/contains) has caused
bugs in the past. This makes BitVector have methods both for set operations on bits and array
operations on bits. I think that's good, since BitVector gets used in both contexts.
* b3/B3IndexSet.h:
(JSC::B3::IndexSet::Iterable::iterator::iterator):
(JSC::B3::IndexSet::Iterable::begin):
(JSC::B3::IndexSet::dump):
* b3/air/AirInstInlines.h:
(JSC::B3::Air::ForEach<Tmp>::forEach):
(JSC::B3::Air::ForEach<Arg>::forEach):
(JSC::B3::Air::ForEach<Reg>::forEach):
(JSC::B3::Air::Inst::forEach):
* b3/air/AirLiveness.h:
(JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter):
(JSC::B3::Air::RegLivenessAdapter::maxIndex):
(JSC::B3::Air::RegLivenessAdapter::acceptsType):
(JSC::B3::Air::RegLivenessAdapter::valueToIndex):
(JSC::B3::Air::RegLivenessAdapter::indexToValue):
* b3/air/AirReportUsedRegisters.cpp:
(JSC::B3::Air::reportUsedRegisters):
* jit/Reg.h:
(JSC::Reg::next):
(JSC::Reg::index):
(JSC::Reg::maxIndex):
(JSC::Reg::isSet):
(JSC::Reg::operator bool):
* jit/RegisterSet.h:
(JSC::RegisterSet::forEach):
Source/WTF:
Add set methods (add/contains/remove) to BitVector, since it gets used as a set in a lot of
places. This also makes BitVector a drop-in replacement for HashSet<unsigned> in a lot of
places.
Also made the iterator methods of BitVector live on BitVector directly rather than behind the
thing returned from setBits(). This makes sense since that makes BitVector even more of a
drop-in for HashSet. It's not harmful since we've never added any other mode of iterating a
BitVector other than this, so it doesn't make sense to make it harder to access.
* wtf/BitVector.h:
(WTF::BitVector::get):
(WTF::BitVector::contains):
(WTF::BitVector::set):
(WTF::BitVector::add):
(WTF::BitVector::ensureSizeAndSet):
(WTF::BitVector::clear):
(WTF::BitVector::remove):
(WTF::BitVector::hash):
(WTF::BitVector::iterator::iterator):
(WTF::BitVector::iterator::operator*):
(WTF::BitVector::iterator::operator++):
(WTF::BitVector::iterator::operator==):
(WTF::BitVector::iterator::operator!=):
(WTF::BitVector::begin):
(WTF::BitVector::end):
(WTF::BitVector::bitsInPointer):
(WTF::BitVector::SetBitsIterable::SetBitsIterable): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::iterator): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator*): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator++): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator==): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator!=): Deleted.
(WTF::BitVector::SetBitsIterable::begin): Deleted.
(WTF::BitVector::SetBitsIterable::end): Deleted.
(WTF::BitVector::setBits): Deleted.
Canonical link: https://commits.webkit.org/171043@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@194834 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-01-11 00:58:34 +00:00
|
|
|
|
2011-09-21 23:36:35 +00:00
|
|
|
private:
|
2019-01-22 18:00:14 +00:00
|
|
|
friend class JSC::CachedBitVector;
|
|
|
|
|
2011-09-21 23:36:35 +00:00
|
|
|
static unsigned bitsInPointer()
|
|
|
|
{
|
|
|
|
return sizeof(void*) << 3;
|
|
|
|
}
|
2012-03-27 00:12:20 +00:00
|
|
|
|
2011-09-21 23:36:35 +00:00
|
|
|
static unsigned maxInlineBits()
|
|
|
|
{
|
|
|
|
return bitsInPointer() - 1;
|
|
|
|
}
|
2012-03-27 00:12:20 +00:00
|
|
|
|
2011-09-21 23:36:35 +00:00
|
|
|
static size_t byteCount(size_t bitCount)
|
|
|
|
{
|
2011-09-24 02:07:58 +00:00
|
|
|
return (bitCount + 7) >> 3;
|
2011-09-21 23:36:35 +00:00
|
|
|
}
|
2012-03-27 00:12:20 +00:00
|
|
|
|
2011-09-21 23:36:35 +00:00
|
|
|
static uintptr_t makeInlineBits(uintptr_t bits)
|
|
|
|
{
|
2011-12-01 09:05:16 +00:00
|
|
|
ASSERT(!(bits & (static_cast<uintptr_t>(1) << maxInlineBits())));
|
|
|
|
return bits | (static_cast<uintptr_t>(1) << maxInlineBits());
|
2011-09-21 23:36:35 +00:00
|
|
|
}
|
|
|
|
|
2013-10-21 04:48:29 +00:00
|
|
|
static uintptr_t cleanseInlineBits(uintptr_t bits)
|
|
|
|
{
|
|
|
|
return bits & ~(static_cast<uintptr_t>(1) << maxInlineBits());
|
|
|
|
}
|
|
|
|
|
2013-10-23 18:22:09 +00:00
|
|
|
static size_t bitCount(uintptr_t bits)
|
|
|
|
{
|
|
|
|
if (sizeof(uintptr_t) == 4)
|
|
|
|
return WTF::bitCount(static_cast<unsigned>(bits));
|
|
|
|
return WTF::bitCount(static_cast<uint64_t>(bits));
|
|
|
|
}
|
|
|
|
|
2014-09-04 21:08:38 +00:00
|
|
|
size_t findBitFast(size_t startIndex, bool value) const
|
|
|
|
{
|
|
|
|
if (isInline()) {
|
|
|
|
size_t index = startIndex;
|
|
|
|
findBitInWord(m_bitsOrPointer, index, maxInlineBits(), value);
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
const OutOfLineBits* bits = outOfLineBits();
|
|
|
|
|
|
|
|
// value = true: casts to 1, then xors to 0, then negates to 0.
|
|
|
|
// value = false: casts to 0, then xors to 1, then negates to -1 (i.e. all one bits).
|
|
|
|
uintptr_t skipValue = -(static_cast<uintptr_t>(value) ^ 1);
|
|
|
|
size_t numWords = bits->numWords();
|
|
|
|
|
|
|
|
size_t wordIndex = startIndex / bitsInPointer();
|
|
|
|
size_t startIndexInWord = startIndex - wordIndex * bitsInPointer();
|
|
|
|
|
|
|
|
while (wordIndex < numWords) {
|
|
|
|
uintptr_t word = bits->bits()[wordIndex];
|
|
|
|
if (word != skipValue) {
|
|
|
|
size_t index = startIndexInWord;
|
|
|
|
if (findBitInWord(word, index, bitsInPointer(), value))
|
|
|
|
return wordIndex * bitsInPointer() + index;
|
|
|
|
}
|
|
|
|
|
|
|
|
wordIndex++;
|
|
|
|
startIndexInWord = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bits->numBits();
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t findBitSimple(size_t index, bool value) const
|
|
|
|
{
|
|
|
|
while (index < size()) {
|
|
|
|
if (get(index) == value)
|
|
|
|
return index;
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
return size();
|
|
|
|
}
|
|
|
|
|
2011-09-21 23:36:35 +00:00
|
|
|
class OutOfLineBits {
|
|
|
|
public:
|
|
|
|
size_t numBits() const { return m_numBits; }
|
2018-02-16 21:38:53 +00:00
|
|
|
size_t numWords() const { return (m_numBits + bitsInPointer() - 1) / bitsInPointer(); }
|
2011-09-24 02:07:58 +00:00
|
|
|
uintptr_t* bits() { return bitwise_cast<uintptr_t*>(this + 1); }
|
|
|
|
const uintptr_t* bits() const { return bitwise_cast<const uintptr_t*>(this + 1); }
|
2011-09-21 23:36:35 +00:00
|
|
|
|
2012-03-23 07:14:29 +00:00
|
|
|
static WTF_EXPORT_PRIVATE OutOfLineBits* create(size_t numBits);
|
2011-09-21 23:36:35 +00:00
|
|
|
|
2012-03-23 07:14:29 +00:00
|
|
|
static WTF_EXPORT_PRIVATE void destroy(OutOfLineBits*);
|
2011-09-21 23:36:35 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
OutOfLineBits(size_t numBits)
|
|
|
|
: m_numBits(numBits)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t m_numBits;
|
|
|
|
};
|
|
|
|
|
2011-12-01 09:05:16 +00:00
|
|
|
bool isInline() const { return m_bitsOrPointer >> maxInlineBits(); }
|
2011-09-21 23:36:35 +00:00
|
|
|
|
2011-12-01 09:05:16 +00:00
|
|
|
const OutOfLineBits* outOfLineBits() const { return bitwise_cast<const OutOfLineBits*>(m_bitsOrPointer << 1); }
|
|
|
|
OutOfLineBits* outOfLineBits() { return bitwise_cast<OutOfLineBits*>(m_bitsOrPointer << 1); }
|
2011-09-21 23:36:35 +00:00
|
|
|
|
2012-03-23 07:14:29 +00:00
|
|
|
WTF_EXPORT_PRIVATE void resizeOutOfLine(size_t numBits);
|
|
|
|
WTF_EXPORT_PRIVATE void setSlow(const BitVector& other);
|
2011-09-21 23:36:35 +00:00
|
|
|
|
2013-10-21 04:48:29 +00:00
|
|
|
WTF_EXPORT_PRIVATE void mergeSlow(const BitVector& other);
|
Switch FTL GetById/PutById IC's over to using AnyRegCC
https://bugs.webkit.org/show_bug.cgi?id=124094
Source/JavaScriptCore:
Reviewed by Sam Weinig.
This closes the loop on inline caches (IC's) in the FTL. The goal is to have IC's
in LLVM-generated code that are just as efficient (if not more so) than what a
custom JIT could do. As in zero sources of overhead. Not a single extra instruction
or even register allocation pathology. We accomplish this by having two thingies in
LLVM. First is the llvm.experimental.patchpoint intrinsic, which is sort of an
inline machine code snippet that we can fill in with whatever we want and then
modify subsequently. But you have only two choices of how to pass values to a
patchpoint: (1) via the calling convention or (2) via the stackmap. Neither are good
for operands to an IC (like the base pointer for a GetById, for example). (1) is bad
because it results in things being pinned to certain registers a priori; a custom
JIT (like the DFG) will not pin IC operands to any registers a priori but will allow
the register allocator to do whatever it wants. (2) is bad because the operands may
be spilled or may be represented in other crazy ways. You generally want an IC to
have its operands in registers. Also, patchpoints only return values using the
calling convention, which is unfortunate since it pins the return value to a
register a priori. This is where the second thingy comes in: the AnyRegCC. This is
a special calling convention only for use with patchpoints. It means that arguments
passed "by CC" in the patchpoint can be placed in any register, and the register
that gets used is reported as part of the stackmap. It also means that the return
value (if there is one) can be placed in any register, and the stackmap will tell
you which one it was. Thus, patchpoints combined with AnyRegCC mean that you not
only get the kind of self-modifying code that you want for IC's, but you also get
all of the register allocation goodness that a custom JIT would have given you.
Except that you're getting it from LLVM and not a custom JIT. Awesome.
Even though all of the fun stuff is on the LLVM side, this patch was harder than
you'd expect.
First the obvious bits:
- IC patchpoints now use AnyRegCC instead of the C CC. (CC = calling convention.)
- FTL::fixFunctionBasedOnStackMaps() now correctly figures out which registers the
IC is supposed to use instead of assuming C CC argument registers.
And then all of the stuff that broke and that this patch fixes:
- IC sizing based on generating a dummy IC (what FTLInlineCacheSize did) is totally
bad on x86-64, where various register permutations lead to bizarre header bytes
and eclectic SIB encodings. I changed that to have magic constants, for now.
- Slow path calls didn't preserve the CC return register.
- Repatch's scratch register allocation would get totally confused if the operand
registers weren't one of the DFG-style "temp" registers. And by "totally confused"
I mean that it would crash.
- We assumed that r10 is callee-saved. It's not. That one dude's PPT about x86-64
cdecl that I found on the intertubes was not a trustworthy source of information,
apparently.
- Call repatching didn't know that the FTL does its IC slow calls via specially
generated thunks. This was particularly fun to fix: basically, now when we relink
an IC call in the FTL, we use the old call target to find the SlowPathCallKey,
which tells us everything we need to know to generate (or look up) a new thunk for
the new function we want to call.
* assembler/MacroAssemblerCodeRef.h:
(JSC::MacroAssemblerCodePtr::MacroAssemblerCodePtr):
(JSC::MacroAssemblerCodePtr::isEmptyValue):
(JSC::MacroAssemblerCodePtr::isDeletedValue):
(JSC::MacroAssemblerCodePtr::hash):
(JSC::MacroAssemblerCodePtr::emptyValue):
(JSC::MacroAssemblerCodePtr::deletedValue):
(JSC::MacroAssemblerCodePtrHash::hash):
(JSC::MacroAssemblerCodePtrHash::equal):
* assembler/MacroAssemblerX86Common.h:
* assembler/RepatchBuffer.h:
(JSC::RepatchBuffer::RepatchBuffer):
(JSC::RepatchBuffer::codeBlock):
* ftl/FTLAbbreviations.h:
(JSC::FTL::setInstructionCallingConvention):
* ftl/FTLCompile.cpp:
(JSC::FTL::fixFunctionBasedOnStackMaps):
* ftl/FTLInlineCacheSize.cpp:
(JSC::FTL::sizeOfGetById):
(JSC::FTL::sizeOfPutById):
* ftl/FTLJITFinalizer.cpp:
(JSC::FTL::JITFinalizer::finalizeFunction):
* ftl/FTLLocation.cpp:
(JSC::FTL::Location::forStackmaps):
* ftl/FTLLocation.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileGetById):
(JSC::FTL::LowerDFGToLLVM::compilePutById):
* ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::compileStub):
* ftl/FTLSlowPathCall.cpp:
* ftl/FTLSlowPathCallKey.h:
(JSC::FTL::SlowPathCallKey::withCallTarget):
* ftl/FTLStackMaps.cpp:
(JSC::FTL::StackMaps::Location::directGPR):
(JSC::FTL::StackMaps::Location::restoreInto):
* ftl/FTLStackMaps.h:
* ftl/FTLThunks.h:
(JSC::FTL::generateIfNecessary):
(JSC::FTL::keyForThunk):
(JSC::FTL::Thunks::keyForSlowPathCallThunk):
* jit/FPRInfo.h:
(JSC::FPRInfo::toIndex):
* jit/GPRInfo.h:
(JSC::GPRInfo::toIndex):
(JSC::GPRInfo::debugName):
* jit/RegisterSet.cpp:
(JSC::RegisterSet::calleeSaveRegisters):
* jit/RegisterSet.h:
(JSC::RegisterSet::filter):
* jit/Repatch.cpp:
(JSC::readCallTarget):
(JSC::repatchCall):
(JSC::repatchByIdSelfAccess):
(JSC::tryCacheGetByID):
(JSC::tryCachePutByID):
(JSC::tryBuildPutByIdList):
(JSC::resetGetByID):
(JSC::resetPutByID):
* jit/ScratchRegisterAllocator.h:
(JSC::ScratchRegisterAllocator::lock):
Source/WTF:
Reviewed by Sam Weinig.
I needed to add another set operation, namely filter(), which is an in-place set
intersection.
* wtf/BitVector.cpp:
(WTF::BitVector::filterSlow):
* wtf/BitVector.h:
(WTF::BitVector::filter):
Canonical link: https://commits.webkit.org/142336@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@159039 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2013-11-11 07:30:50 +00:00
|
|
|
WTF_EXPORT_PRIVATE void filterSlow(const BitVector& other);
|
2013-10-23 18:22:09 +00:00
|
|
|
WTF_EXPORT_PRIVATE void excludeSlow(const BitVector& other);
|
|
|
|
|
|
|
|
WTF_EXPORT_PRIVATE size_t bitCountSlow() const;
|
2019-05-07 20:46:43 +00:00
|
|
|
WTF_EXPORT_PRIVATE bool isEmptySlow() const;
|
2013-10-23 18:22:09 +00:00
|
|
|
|
|
|
|
WTF_EXPORT_PRIVATE bool equalsSlowCase(const BitVector& other) const;
|
2014-09-04 21:08:38 +00:00
|
|
|
bool equalsSlowCaseFast(const BitVector& other) const;
|
|
|
|
bool equalsSlowCaseSimple(const BitVector& other) const;
|
2013-10-23 18:22:09 +00:00
|
|
|
WTF_EXPORT_PRIVATE uintptr_t hashSlowCase() const;
|
2013-10-21 04:48:29 +00:00
|
|
|
|
2011-09-21 23:36:35 +00:00
|
|
|
uintptr_t* bits()
|
|
|
|
{
|
|
|
|
if (isInline())
|
|
|
|
return &m_bitsOrPointer;
|
|
|
|
return outOfLineBits()->bits();
|
|
|
|
}
|
|
|
|
|
|
|
|
const uintptr_t* bits() const
|
|
|
|
{
|
|
|
|
if (isInline())
|
|
|
|
return &m_bitsOrPointer;
|
|
|
|
return outOfLineBits()->bits();
|
|
|
|
}
|
2011-12-01 09:05:16 +00:00
|
|
|
|
2011-09-21 23:36:35 +00:00
|
|
|
uintptr_t m_bitsOrPointer;
|
|
|
|
};
|
|
|
|
|
2013-10-23 18:22:09 +00:00
|
|
|
struct BitVectorHash {
|
|
|
|
static unsigned hash(const BitVector& vector) { return vector.hash(); }
|
|
|
|
static bool equal(const BitVector& a, const BitVector& b) { return a == b; }
|
2019-09-18 00:36:19 +00:00
|
|
|
static constexpr bool safeToCompareToEmptyOrDeleted = false;
|
2013-10-23 18:22:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T> struct DefaultHash;
|
2020-07-17 00:33:37 +00:00
|
|
|
template<> struct DefaultHash<BitVector> : BitVectorHash { };
|
2013-10-23 18:22:09 +00:00
|
|
|
|
|
|
|
template<> struct HashTraits<BitVector> : public CustomHashTraits<BitVector> { };
|
|
|
|
|
2011-09-21 23:36:35 +00:00
|
|
|
} // namespace WTF
|
|
|
|
|
|
|
|
using WTF::BitVector;
|