Skip to content

Instantly share code, notes, and snippets.

@StepS-
Last active May 23, 2018 22:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StepS-/436098ac8979217d263bab2edab11ee5 to your computer and use it in GitHub Desktop.
Save StepS-/436098ac8979217d263bab2edab11ee5 to your computer and use it in GitHub Desktop.
diff --git a/Source/WTF/wtf/MathExtras.h b/Source/WTF/wtf/MathExtras.h
index 99717ba..eca49d4 100644
--- a/Source/WTF/wtf/MathExtras.h
+++ b/Source/WTF/wtf/MathExtras.h
@@ -450,6 +450,13 @@ inline uint32_t roundUpToPowerOfTwo(uint32_t v)
return v;
}
+inline unsigned maskForSize(unsigned size)
+{
+ if (!size)
+ return 0;
+ return roundUpToPowerOfTwo(size) - 1;
+}
+
inline unsigned fastLog2(unsigned i)
{
unsigned log2 = 0;
diff --git a/Source/WTF/wtf/SizeLimits.cpp b/Source/WTF/wtf/SizeLimits.cpp
index 538f460..07daaa6 100644
--- a/Source/WTF/wtf/SizeLimits.cpp
+++ b/Source/WTF/wtf/SizeLimits.cpp
@@ -59,6 +59,7 @@ struct SameSizeAsVectorWithInlineCapacity {
void* bufferPointer;
unsigned capacity;
unsigned size;
+ unsigned mask;
AlignedBuffer<inlineCapacity * sizeof(T), WTF_ALIGN_OF(T)> inlineBuffer;
};
diff --git a/Source/WTF/wtf/Vector.h b/Source/WTF/wtf/Vector.h
index be7c4b2..442a890 100644
--- a/Source/WTF/wtf/Vector.h
+++ b/Source/WTF/wtf/Vector.h
@@ -24,6 +24,8 @@
#include <wtf/Alignment.h>
#include <wtf/CheckedArithmetic.h>
#include <wtf/FastAllocBase.h>
+#include <wtf/MathExtras.h>
+#include <wtf/Noncopyable.h>
#include <wtf/Noncopyable.h>
#include <wtf/NotFound.h>
#include <wtf/StdLibExtras.h>
@@ -256,6 +258,7 @@ namespace WTF {
CRASH();
size_t sizeToAllocate = fastMallocGoodSize(newCapacity * sizeof(T));
m_capacity = sizeToAllocate / sizeof(T);
+ updateMask();
m_buffer = static_cast<T*>(
#if ENABLE(DETACHED_JIT)
shared ? JITSharedDataMemory::shared_malloc(sizeToAllocate) :
@@ -280,6 +283,7 @@ namespace WTF {
);
if (tryMallocResult.getValue(newBuffer)) {
m_capacity = sizeToAllocate / sizeof(T);
+ updateMask();
m_buffer = newBuffer;
return true;
}
@@ -298,6 +302,7 @@ namespace WTF {
CRASH();
size_t sizeToAllocate = fastMallocGoodSize(newCapacity * sizeof(T));
m_capacity = sizeToAllocate / sizeof(T);
+ updateMask();
m_buffer = static_cast<T*>(
#if ENABLE(DETACHED_JIT)
shared ? JITSharedDataMemory::shared_realloc(m_buffer, sizeToAllocate) :
@@ -314,6 +319,7 @@ namespace WTF {
if (m_buffer == bufferToDeallocate) {
m_buffer = 0;
m_capacity = 0;
+ m_mask = 0;
}
#if ENABLE(DETACHED_JIT)
@@ -331,6 +337,7 @@ namespace WTF {
T* buffer = m_buffer;
m_buffer = 0;
m_capacity = 0;
+ m_mask = 0;
return buffer;
}
@@ -339,6 +346,7 @@ namespace WTF {
: m_buffer(0)
, m_capacity(0)
, m_size(0)
+ , m_mask(0)
{
}
@@ -346,7 +354,9 @@ namespace WTF {
: m_buffer(buffer)
, m_capacity(capacity)
, m_size(size)
+ , m_mask(0)
{
+ updateMask();
}
~VectorBufferBase()
@@ -354,9 +364,15 @@ namespace WTF {
// FIXME: It would be nice to find a way to ASSERT that m_buffer hasn't leaked here.
}
+ void updateMask()
+ {
+ m_mask = maskForSize(m_capacity);
+ }
+
T* m_buffer;
unsigned m_capacity;
unsigned m_size; // Only used by the Vector subclass, but placed here to avoid padding the struct.
+ unsigned m_mask;
};
template<typename T, size_t inlineCapacity, bool shared>
@@ -389,6 +405,7 @@ namespace WTF {
{
std::swap(m_buffer, other.m_buffer);
std::swap(m_capacity, other.m_capacity);
+ std::swap(m_mask, other.m_mask);
}
void restoreInlineBufferIfNeeded() { }
@@ -405,6 +422,7 @@ namespace WTF {
using Base::releaseBuffer;
protected:
+ using Base::m_mask;
using Base::m_size;
private:
@@ -443,6 +461,7 @@ namespace WTF {
else {
m_buffer = inlineBuffer();
m_capacity = inlineCapacity;
+ updateMask();
}
}
@@ -452,6 +471,7 @@ namespace WTF {
return Base::tryAllocateBuffer(newCapacity);
m_buffer = inlineBuffer();
m_capacity = inlineCapacity;
+ updateMask();
return true;
}
@@ -479,19 +499,23 @@ namespace WTF {
if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuffer()) {
WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
std::swap(m_capacity, other.m_capacity);
+ std::swap(m_mask, other.m_mask);
} else if (buffer() == inlineBuffer()) {
m_buffer = other.m_buffer;
other.m_buffer = other.inlineBuffer();
WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
std::swap(m_capacity, other.m_capacity);
+ std::swap(m_mask, other.m_mask);
} else if (other.buffer() == other.inlineBuffer()) {
other.m_buffer = m_buffer;
m_buffer = inlineBuffer();
WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
std::swap(m_capacity, other.m_capacity);
+ std::swap(m_mask, other.m_mask);
} else {
std::swap(m_buffer, other.m_buffer);
std::swap(m_capacity, other.m_capacity);
+ std::swap(m_mask, other.m_mask);
}
}
@@ -501,6 +525,7 @@ namespace WTF {
return;
m_buffer = inlineBuffer();
m_capacity = inlineCapacity;
+ updateMask();
}
using Base::buffer;
@@ -514,11 +539,13 @@ namespace WTF {
}
protected:
+ using Base::m_mask;
using Base::m_size;
private:
using Base::m_buffer;
using Base::m_capacity;
+ using Base::updateMask;
static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffer); }
@@ -697,6 +724,7 @@ namespace WTF {
template<typename U> U* expandCapacity(size_t newMinCapacity, U*);
template<typename U> void appendSlowCase(const U&);
+ using Base::m_mask;
using Base::m_size;
using Base::buffer;
using Base::capacity;
diff --git a/Source/WTF/wtf/text/StringImpl.cpp b/Source/WTF/wtf/text/StringImpl.cpp
index 62f5735..9073313 100644
--- a/Source/WTF/wtf/text/StringImpl.cpp
+++ b/Source/WTF/wtf/text/StringImpl.cpp
@@ -44,7 +44,7 @@ namespace WTF {
using namespace Unicode;
-COMPILE_ASSERT(sizeof(StringImpl) == 2 * sizeof(int) + 3 * sizeof(void*), StringImpl_should_stay_small);
+COMPILE_ASSERT(sizeof(StringImpl) == 2 * sizeof(int) + 3 * sizeof(void*) + sizeof(int), StringImpl_should_stay_small);
#ifdef STRING_STATS
StringStats StringImpl::m_stringStats;
diff --git a/Source/WTF/wtf/text/StringImpl.h b/Source/WTF/wtf/text/StringImpl.h
index cb2ccb1..6789092 100644
--- a/Source/WTF/wtf/text/StringImpl.h
+++ b/Source/WTF/wtf/text/StringImpl.h
@@ -26,6 +26,7 @@
#include <limits.h>
#include <wtf/ASCIICType.h>
#include <wtf/Forward.h>
+#include <WTF/MathExtras.h>
#include <wtf/StdLibExtras.h>
#include <wtf/StringHasher.h>
#include <wtf/Vector.h>
@@ -181,6 +182,7 @@ private:
, m_data16(characters)
, m_buffer(0)
, m_hashAndFlags(s_hashFlagIsIdentifier | BufferOwned)
+ , m_mask(maskForSize(length))
{
// Ensure that the hash is computed so that AtomicStringHash can call existingHash()
// with impunity. The empty string is special because it is never entered into
@@ -199,6 +201,7 @@ private:
, m_data8(characters)
, m_buffer(0)
, m_hashAndFlags(s_hashFlag8BitBuffer | s_hashFlagIsIdentifier | BufferOwned)
+ , m_mask(maskForSize(length))
{
// Ensure that the hash is computed so that AtomicStringHash can call existingHash()
// with impunity. The empty string is special because it is never entered into
@@ -217,6 +220,7 @@ private:
, m_data8(reinterpret_cast<const LChar*>(this + 1))
, m_buffer(0)
, m_hashAndFlags(s_hashFlag8BitBuffer | BufferInternal)
+ , m_mask(maskForSize(length))
{
ASSERT(m_data8);
ASSERT(m_length);
@@ -231,6 +235,7 @@ private:
, m_data16(reinterpret_cast<const UChar*>(this + 1))
, m_buffer(0)
, m_hashAndFlags(BufferInternal)
+ , m_mask(maskForSize(length))
{
ASSERT(m_data16);
ASSERT(m_length);
@@ -245,6 +250,7 @@ private:
, m_data8(characters)
, m_buffer(0)
, m_hashAndFlags(s_hashFlag8BitBuffer | BufferOwned)
+ , m_mask(maskForSize(length))
{
ASSERT(m_data8);
ASSERT(m_length);
@@ -259,6 +265,7 @@ private:
, m_data16(characters)
, m_buffer(0)
, m_hashAndFlags(BufferInternal | (hasTerminatingNullCharacter ? s_hashFlagHasTerminatingNullCharacter : 0))
+ , m_mask(maskForSize(length))
{
ASSERT(m_data16);
ASSERT(m_length);
@@ -273,6 +280,7 @@ private:
, m_data8(characters)
, m_buffer(0)
, m_hashAndFlags(s_hashFlag8BitBuffer | BufferInternal | (hasTerminatingNullCharacter ? s_hashFlagHasTerminatingNullCharacter : 0))
+ , m_mask(maskForSize(length))
{
ASSERT(m_data8);
ASSERT(m_length);
@@ -288,6 +296,7 @@ private:
, m_data16(characters)
, m_buffer(0)
, m_hashAndFlags(BufferOwned)
+ , m_mask(maskForSize(length))
{
ASSERT(m_data16);
ASSERT(m_length);
@@ -302,6 +311,7 @@ private:
, m_data8(characters)
, m_substringBuffer(base.leakRef())
, m_hashAndFlags(s_hashFlag8BitBuffer | BufferSubstring)
+ , m_mask(maskForSize(length))
{
ASSERT(is8Bit());
ASSERT(m_data8);
@@ -318,6 +328,7 @@ private:
, m_data16(characters)
, m_substringBuffer(base.leakRef())
, m_hashAndFlags(BufferSubstring)
+ , m_mask(maskForSize(length))
{
ASSERT(!is8Bit());
ASSERT(m_data16);
@@ -333,6 +344,7 @@ private:
, m_length(0)
, m_data16(reinterpret_cast<const UChar*>(1))
, m_buffer(0)
+ , m_mask(maskForSize(0))
{
ASSERT(m_data16);
// Set the hash early, so that all empty unique StringImpls have a hash,
@@ -358,6 +370,7 @@ private:
, m_data16(0)
, m_qStringData(qStringData)
, m_hashAndFlags(BufferAdoptedQString)
+ , m_mask(maskForSize(qStringData->size)))
{
ASSERT(m_length);
@@ -485,6 +498,7 @@ public:
static PassRefPtr<StringImpl> reallocate(PassRefPtr<StringImpl> originalString, unsigned length, UChar*& data);
static unsigned flagsOffset() { return OBJECT_OFFSETOF(StringImpl, m_hashAndFlags); }
+ static unsigned maskOffset() { return OBJECT_OFFSETOF(StringImpl, m_mask); }
static unsigned flagIs8Bit() { return s_hashFlag8BitBuffer; }
static unsigned dataOffset() { return OBJECT_OFFSETOF(StringImpl, m_data8); }
static PassRefPtr<StringImpl> createWithTerminatingNullCharacter(const StringImpl&);
@@ -687,8 +701,8 @@ public:
{
ASSERT_WITH_SECURITY_IMPLICATION(i < m_length);
if (is8Bit())
- return m_data8[i];
- return m_data16[i];
+ return m_data8[i & m_mask];
+ return m_data16[i & m_mask];
}
WTF_EXPORT_STRING_API UChar32 characterStartingAt(unsigned);
@@ -830,6 +844,7 @@ public:
const LChar* m_data8;
void* m_buffer;
unsigned m_hashAndFlags;
+ unsigned m_mask;
// These values mimic ConstructFromLiteral.
static const unsigned s_initialRefCount = s_refCountIncrement;
@@ -862,6 +877,7 @@ private:
#endif
};
mutable unsigned m_hashAndFlags;
+ unsigned m_mask;
};
COMPILE_ASSERT(sizeof(StringImpl) == sizeof(StringImpl::StaticASCIILiteral), StringImpl_should_match_its_StaticASCIILiteral);
diff --git a/Source/WebCore/bindings/scripts/StaticString.pm b/Source/WebCore/bindings/scripts/StaticString.pm
index a10e3c8..4285085 100644
--- a/Source/WebCore/bindings/scripts/StaticString.pm
+++ b/Source/WebCore/bindings/scripts/StaticString.pm
@@ -42,13 +42,15 @@ sub GenerateStrings($)
while ( my ($name, $value) = each %strings ) {
my $length = length($value);
my $hash = Hasher::GenerateHashValue($value);
+ my $mask = CalculateMaskFromValue($length);
push(@result, <<END);
static StringImpl::StaticASCIILiteral ${name}Data = {
StringImpl::StaticASCIILiteral::s_initialRefCount,
$length,
${name}String8,
0,
- StringImpl::StaticASCIILiteral::s_initialFlags | (${hash} << StringImpl::StaticASCIILiteral::s_hashShift)
+ StringImpl::StaticASCIILiteral::s_initialFlags | (${hash} << StringImpl::StaticASCIILiteral::s_hashShift),
+ $mask
};
END
}
@@ -84,4 +86,20 @@ sub GenerateStringAsserts($)
return join "", @result;
}
+sub CalculateMaskFromValue($)
+{
+ my $v = shift;
+
+ if (!$v) {
+ return 0;
+ }
+
+ $v--;
+ $v |= $v >> 1;
+ $v |= $v >> 2;
+ $v |= $v >> 4;
+ $v |= $v >> 8;
+ $v |= $v >> 16;
+}
+
1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment