Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (287219 => 287220)
--- trunk/Source/_javascript_Core/ChangeLog 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/_javascript_Core/ChangeLog 2021-12-18 10:17:05 UTC (rev 287220)
@@ -1,3 +1,52 @@
+2021-12-17 Yusuke Suzuki <[email protected]>
+
+ [WTF] Introduce TrailingArray
+ https://bugs.webkit.org/show_bug.cgi?id=234201
+
+ Reviewed by Darin Adler.
+
+ Use ThreadSafeRefCountedFixedVector in ObjectPropertyConditionSet and Wasm::LLIntCallees.
+
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::baselineJITConstantPool):
+ * bytecode/ObjectPropertyConditionSet.cpp:
+ (JSC::ObjectPropertyConditionSet::mergedWith const):
+ (JSC::ObjectPropertyConditionSet::dumpInContext const):
+ (JSC::ObjectPropertyConditionSet::isValidAndWatchable const):
+ * bytecode/ObjectPropertyConditionSet.h:
+ (JSC::ObjectPropertyConditionSet::invalid):
+ (JSC::ObjectPropertyConditionSet::create):
+ (JSC::ObjectPropertyConditionSet::isValid const):
+ (JSC::ObjectPropertyConditionSet::size const):
+ (JSC::ObjectPropertyConditionSet::begin const):
+ (JSC::ObjectPropertyConditionSet::end const):
+ (JSC::ObjectPropertyConditionSet::ObjectPropertyConditionSet): Deleted.
+ (JSC::ObjectPropertyConditionSet::releaseRawPointer): Deleted.
+ (JSC::ObjectPropertyConditionSet::adoptRawPointer): Deleted.
+ (JSC::ObjectPropertyConditionSet::fromRawPointer): Deleted.
+ (JSC::ObjectPropertyConditionSet::Data::Data): Deleted.
+ * jit/JIT.cpp:
+ (JSC::JIT::compileAndLinkWithoutFinalizing):
+ * jit/JITInlines.h:
+ (JSC::JIT::loadConstant):
+ * llint/LLIntOffsetsExtractor.cpp:
+ * llint/LowLevelInterpreter.asm:
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+ * wasm/WasmCallee.h:
+ (JSC::Wasm::LLIntCallees::create): Deleted.
+ (JSC::Wasm::LLIntCallees::at const): Deleted.
+ (JSC::Wasm::LLIntCallees::data const): Deleted.
+ (JSC::Wasm::LLIntCallees::LLIntCallees): Deleted.
+ * wasm/WasmCodeBlock.cpp:
+ (JSC::Wasm::CodeBlock::create):
+ (JSC::Wasm::CodeBlock::CodeBlock):
+ * wasm/WasmCodeBlock.h:
+ * wasm/WasmModule.cpp:
+ (JSC::Wasm::Module::Module):
+ (JSC::Wasm::Module::getOrCreateCodeBlock):
+ * wasm/WasmModule.h:
+
2021-12-17 Saam Barati <[email protected]>
Use IRC by default on arm64
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (287219 => 287220)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2021-12-18 10:17:05 UTC (rev 287220)
@@ -557,7 +557,7 @@
void* baselineJITConstantPool()
{
RELEASE_ASSERT(m_jitData && jitType() == JITType::BaselineJIT);
- return m_jitData->m_jitConstantPool.data();
+ return m_jitData->m_jitConstantPool.storage();
}
#endif
size_t numberOfUnlinkedSwitchJumpTables() const { return m_unlinkedCode->numberOfUnlinkedSwitchJumpTables(); }
Modified: trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.cpp (287219 => 287220)
--- trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.cpp 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.cpp 2021-12-18 10:17:05 UTC (rev 287220)
@@ -105,7 +105,7 @@
Vector<ObjectPropertyCondition> result;
if (!isEmpty())
- result.append(m_data->m_vector.begin(), m_data->m_vector.size());
+ result.append(m_data->begin(), m_data->size());
for (const ObjectPropertyCondition& newCondition : other) {
bool foundMatch = false;
@@ -175,7 +175,7 @@
out.print("[");
if (m_data)
- out.print(listDumpInContext(m_data->m_vector, context));
+ out.print(listDumpInContext(*m_data, context));
out.print("]");
}
@@ -189,7 +189,7 @@
if (!isValid())
return false;
- for (auto& condition : m_data->m_vector) {
+ for (auto& condition : *m_data) {
if (!condition.isWatchable())
return false;
}
Modified: trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.h (287219 => 287220)
--- trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.h 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.h 2021-12-18 10:17:05 UTC (rev 287220)
@@ -27,8 +27,8 @@
#include "ObjectPropertyCondition.h"
#include <wtf/FastMalloc.h>
-#include <wtf/FixedVector.h>
#include <wtf/Hasher.h>
+#include <wtf/RefCountedFixedVector.h>
#include <wtf/Vector.h>
namespace JSC {
@@ -43,12 +43,15 @@
class ObjectPropertyConditionSet {
public:
- ObjectPropertyConditionSet() { }
+ using Conditions = ThreadSafeRefCountedFixedVector<ObjectPropertyCondition>;
+
+ ObjectPropertyConditionSet() = default;
static ObjectPropertyConditionSet invalid()
{
ObjectPropertyConditionSet result;
- result.m_data = adoptRef(new Data());
+ result.m_data = Conditions::create(0);
+ ASSERT(!result.isValid());
return result;
}
@@ -58,37 +61,37 @@
return ObjectPropertyConditionSet();
ObjectPropertyConditionSet result;
- result.m_data = adoptRef(new Data());
- result.m_data->m_vector = FixedVector<ObjectPropertyCondition>(WTFMove(vector));
+ result.m_data = Conditions::createFromVector(WTFMove(vector));
+ ASSERT(result.isValid());
return result;
}
bool isValid() const
{
- return !m_data || !m_data->m_vector.isEmpty();
+ return !m_data || !m_data->isEmpty();
}
bool isValidAndWatchable() const;
- size_t size() const { return m_data ? m_data->m_vector.size() : 0; }
+ size_t size() const { return m_data ? m_data->size() : 0; }
bool isEmpty() const
{
return !m_data;
}
-
- typedef const ObjectPropertyCondition* iterator;
-
- iterator begin() const
+
+ using const_iterator = Conditions::const_iterator;
+
+ const_iterator begin() const
{
if (!m_data)
return nullptr;
- return m_data->m_vector.begin();
+ return m_data->cbegin();
}
- iterator end() const
+ const_iterator end() const
{
if (!m_data)
return nullptr;
- return m_data->m_vector.end();
+ return m_data->cend();
}
unsigned hash() const
@@ -151,45 +154,15 @@
void dumpInContext(PrintStream&, DumpContext*) const;
void dump(PrintStream&) const;
-
- // Helpers for using this in a union.
- void* releaseRawPointer()
- {
- return static_cast<void*>(m_data.leakRef());
- }
- static ObjectPropertyConditionSet adoptRawPointer(void* rawPointer)
- {
- ObjectPropertyConditionSet result;
- result.m_data = adoptRef(static_cast<Data*>(rawPointer));
- return result;
- }
- static ObjectPropertyConditionSet fromRawPointer(void* rawPointer)
- {
- ObjectPropertyConditionSet result;
- result.m_data = static_cast<Data*>(rawPointer);
- return result;
- }
- // FIXME: Everything below here should be private, but cannot be because of a bug in VS.
-
// Internally, this represents Invalid using a pointer to a Data that has an empty vector.
// FIXME: This could be made more compact by having it internally use a vector that just has
// the non-uid portion of ObjectPropertyCondition, and then requiring that the callers of all
// of the APIs supply the uid.
-
- class Data : public ThreadSafeRefCounted<Data> {
- WTF_MAKE_NONCOPYABLE(Data);
- WTF_MAKE_FAST_ALLOCATED;
-
- public:
- Data() { }
-
- FixedVector<ObjectPropertyCondition> m_vector;
- };
-
+
private:
- RefPtr<Data> m_data;
+ RefPtr<Conditions> m_data;
};
ObjectPropertyCondition generateConditionForSelfEquivalence(
Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (287219 => 287220)
--- trunk/Source/_javascript_Core/jit/JIT.cpp 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp 2021-12-18 10:17:05 UTC (rev 287220)
@@ -798,7 +798,7 @@
continue;
int offset = CallFrame::argumentOffsetIncludingThis(argument) * static_cast<int>(sizeof(Register));
loadValue(Address(callFrameRegister, offset), jsRegT10);
- storeValue(jsRegT10, Address(regT2, argument * sizeof(ValueProfile) + ValueProfile::offsetOfFirstBucket()));
+ storeValue(jsRegT10, Address(regT2, FixedVector<ValueProfile>::Storage::offsetOfData() + argument * sizeof(ValueProfile) + ValueProfile::offsetOfFirstBucket()));
}
}
}
Modified: trunk/Source/_javascript_Core/jit/JITInlines.h (287219 => 287220)
--- trunk/Source/_javascript_Core/jit/JITInlines.h 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/_javascript_Core/jit/JITInlines.h 2021-12-18 10:17:05 UTC (rev 287220)
@@ -505,7 +505,7 @@
ALWAYS_INLINE void JIT::loadConstant(JITConstantPool::Constant constantIndex, GPRReg result)
{
- loadPtr(Address(s_constantsGPR, static_cast<uintptr_t>(constantIndex) * sizeof(void*)), result);
+ loadPtr(Address(s_constantsGPR, FixedVector<void*>::Storage::offsetOfData() + static_cast<uintptr_t>(constantIndex) * sizeof(void*)), result);
}
ALWAYS_INLINE void JIT::loadGlobalObject(GPRReg result)
Modified: trunk/Source/_javascript_Core/llint/LLIntOffsetsExtractor.cpp (287219 => 287220)
--- trunk/Source/_javascript_Core/llint/LLIntOffsetsExtractor.cpp 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/_javascript_Core/llint/LLIntOffsetsExtractor.cpp 2021-12-18 10:17:05 UTC (rev 287220)
@@ -87,8 +87,13 @@
// These types are useful since we can't use '<...>' syntax in LLInt offsets extraction. e.g. Vector<int>::m_data
using Vector = WTF::Vector<int>;
using JSInternalFieldObjectImpl = JSC::JSInternalFieldObjectImpl<>;
- using FixedVector = WTF::FixedVector<int>;
- using RefCountedArray = WTF::RefCountedArray<int>;
+ using ValueProfileFixedVector = WTF::FixedVector<ValueProfile>;
+ using BinaryArithProfileFixedVector = FixedVector<BinaryArithProfile>;
+ using UnaryArithProfileFixedVector = FixedVector<UnaryArithProfile>;
+ using UnlinkedSimpleJumpTableFixedVector = FixedVector<UnlinkedSimpleJumpTable>;
+ using UnlinkedStringJumpTableFixedVector = FixedVector<UnlinkedStringJumpTable>;
+ using Int32FixedVector = FixedVector<int32_t>;
+ using VoidPointerFixedVector = FixedVector<void*>;
public:
static const int64_t* dummy();
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (287219 => 287220)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2021-12-18 10:17:05 UTC (rev 287220)
@@ -628,8 +628,6 @@
const VectorBufferOffset = Vector::m_buffer
const VectorSizeOffset = Vector::m_size
-const RefCountedArrayStorageNonNullSizeOffset = -(constexpr (RefCountedArray::Header::size())) + RefCountedArray::Header::length
-
# Some common utilities.
macro crash()
if C_LOOP or C_LOOP_WIN
@@ -1682,10 +1680,11 @@
addp -profileArgSkip, t0
assert(macro (ok) bpgteq t0, 0, ok end)
btpz t0, .argumentProfileDone
- loadp CodeBlock::m_argumentValueProfiles + FixedVector::m_storage + RefCountedArray::m_data[t1], t3
+ loadp CodeBlock::m_argumentValueProfiles + ValueProfileFixedVector::m_storage[t1], t3
btpz t3, .argumentProfileDone # When we can't JIT, we don't allocate any argument value profiles.
mulp sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction!
lshiftp 3, t0 # offset of last JSValue arguments on the stack.
+ addp (constexpr (ValueProfileFixedVector::Storage::offsetOfData())), t3
addp t2, t3 # pointer to end of ValueProfile array in the value profile array.
.argumentProfileLoop:
if JSVALUE64
@@ -2615,7 +2614,7 @@
# Baseline uses LLInt's PB register for its JIT constant pool.
loadp CodeBlock[cfr], PB
loadp CodeBlock::m_jitData[PB], PB
- loadp CodeBlock::JITData::m_jitConstantPool[PB], PB
+ loadp CodeBlock::JITData::m_jitConstantPool + VoidPointerFixedVector::m_storage[PB], PB
end
macro setupReturnToBaselineAfterCheckpointExitIfNeeded()
@@ -2730,8 +2729,8 @@
getu(size, opcodeStruct, m_profileIndex, scratch1)
loadp CodeBlock[cfr], scratch2
loadp CodeBlock::m_unlinkedCode[scratch2], scratch2
- loadp UnlinkedCodeBlock::m_unaryArithProfiles + FixedVector::m_storage + RefCountedArray::m_data[scratch2], scratch2
- orh type, UnaryArithProfile::m_bits[scratch2, scratch1, 2]
+ loadp UnlinkedCodeBlock::m_unaryArithProfiles + UnaryArithProfileFixedVector::m_storage[scratch2], scratch2
+ orh type, (constexpr (UnaryArithProfileFixedVector::Storage::offsetOfData())) + UnaryArithProfile::m_bits[scratch2, scratch1, 2]
end
macro updateBinaryArithProfile(size, opcodeStruct, type, scratch1, scratch2)
@@ -2738,8 +2737,8 @@
getu(size, opcodeStruct, m_profileIndex, scratch1)
loadp CodeBlock[cfr], scratch2
loadp CodeBlock::m_unlinkedCode[scratch2], scratch2
- loadp UnlinkedCodeBlock::m_binaryArithProfiles + FixedVector::m_storage + RefCountedArray::m_data[scratch2], scratch2
- orh type, BinaryArithProfile::m_bits[scratch2, scratch1, 2]
+ loadp UnlinkedCodeBlock::m_binaryArithProfiles + BinaryArithProfileFixedVector::m_storage[scratch2], scratch2
+ orh type, (constexpr (BinaryArithProfileFixedVector::Storage::offsetOfData())) + BinaryArithProfile::m_bits[scratch2, scratch1, 2]
end
// FIXME: We should not need the X86_64_WIN condition here, since WEBASSEMBLY should already be false on Windows
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (287219 => 287220)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2021-12-18 10:17:05 UTC (rev 287220)
@@ -2099,14 +2099,15 @@
loadp CodeBlock::m_unlinkedCode[t2], t2
loadp UnlinkedCodeBlock::m_rareData[t2], t2
muli sizeof UnlinkedSimpleJumpTable, t3
- loadp UnlinkedCodeBlock::RareData::m_unlinkedSwitchJumpTables + FixedVector::m_storage + RefCountedArray::m_data[t2], t2
+ loadp UnlinkedCodeBlock::RareData::m_unlinkedSwitchJumpTables + UnlinkedSimpleJumpTableFixedVector::m_storage[t2], t2
+ addp (constexpr (UnlinkedSimpleJumpTableFixedVector::Storage::offsetOfData())), t2
addp t3, t2
bineq t1, Int32Tag, .opSwitchImmNotInt
subi UnlinkedSimpleJumpTable::m_min[t2], t0
- loadp UnlinkedSimpleJumpTable::m_branchOffsets + FixedVector::m_storage + RefCountedArray::m_data[t2], t2
+ loadp UnlinkedSimpleJumpTable::m_branchOffsets + Int32FixedVector::m_storage[t2], t2
btpz t2, .opSwitchImmFallThrough
- biaeq t0, RefCountedArrayStorageNonNullSizeOffset[t2], .opSwitchImmFallThrough
- loadi [t2, t0, 4], t1
+ biaeq t0, Int32FixedVector::Storage::m_size[t2], .opSwitchImmFallThrough
+ loadi (constexpr (Int32FixedVector::Storage::offsetOfData()))[t2, t0, 4], t1
btiz t1, .opSwitchImmFallThrough
dispatchIndirect(t1)
@@ -2129,7 +2130,8 @@
loadp CodeBlock::m_unlinkedCode[t2], t2
loadp UnlinkedCodeBlock::m_rareData[t2], t2
muli sizeof UnlinkedSimpleJumpTable, t3
- loadp UnlinkedCodeBlock::RareData::m_unlinkedSwitchJumpTables + FixedVector::m_storage + RefCountedArray::m_data[t2], t2
+ loadp UnlinkedCodeBlock::RareData::m_unlinkedSwitchJumpTables + UnlinkedSimpleJumpTableFixedVector::m_storage[t2], t2
+ addp (constexpr (UnlinkedSimpleJumpTableFixedVector::Storage::offsetOfData())), t2
addp t3, t2
bineq t1, CellTag, .opSwitchCharFallThrough
bbneq JSCell::m_type[t0], StringType, .opSwitchCharFallThrough
@@ -2144,10 +2146,10 @@
loadb [t0], t0
.opSwitchCharReady:
subi UnlinkedSimpleJumpTable::m_min[t2], t0
- loadp UnlinkedSimpleJumpTable::m_branchOffsets + FixedVector::m_storage + RefCountedArray::m_data[t2], t2
+ loadp UnlinkedSimpleJumpTable::m_branchOffsets + Int32FixedVector::m_storage[t2], t2
btpz t2, .opSwitchCharFallThrough
- biaeq t0, RefCountedArrayStorageNonNullSizeOffset[t2], .opSwitchCharFallThrough
- loadi [t2, t0, 4], t1
+ biaeq t0, Int32FixedVector::Storage::m_size[t2], .opSwitchCharFallThrough
+ loadi (constexpr (Int32FixedVector::Storage::offsetOfData()))[t2, t0, 4], t1
btiz t1, .opSwitchCharFallThrough
dispatchIndirect(t1)
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (287219 => 287220)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2021-12-18 10:17:05 UTC (rev 287220)
@@ -2308,14 +2308,15 @@
loadp CodeBlock::m_unlinkedCode[t2], t2
loadp UnlinkedCodeBlock::m_rareData[t2], t2
muli sizeof UnlinkedSimpleJumpTable, t3
- loadp UnlinkedCodeBlock::RareData::m_unlinkedSwitchJumpTables + FixedVector::m_storage + RefCountedArray::m_data[t2], t2
+ loadp UnlinkedCodeBlock::RareData::m_unlinkedSwitchJumpTables + UnlinkedSimpleJumpTableFixedVector::m_storage[t2], t2
+ addp (constexpr (UnlinkedSimpleJumpTableFixedVector::Storage::offsetOfData())), t2
addp t3, t2
bqb t1, numberTag, .opSwitchImmNotInt
subi UnlinkedSimpleJumpTable::m_min[t2], t1
- loadp UnlinkedSimpleJumpTable::m_branchOffsets + FixedVector::m_storage + RefCountedArray::m_data[t2], t2
+ loadp UnlinkedSimpleJumpTable::m_branchOffsets + Int32FixedVector::m_storage[t2], t2
btpz t2, .opSwitchImmFallThrough
- biaeq t1, RefCountedArrayStorageNonNullSizeOffset[t2], .opSwitchImmFallThrough
- loadis [t2, t1, 4], t1
+ biaeq t1, Int32FixedVector::Storage::m_size[t2], .opSwitchImmFallThrough
+ loadis (constexpr (Int32FixedVector::Storage::offsetOfData()))[t2, t1, 4], t1
btiz t1, .opSwitchImmFallThrough
dispatchIndirect(t1)
@@ -2338,7 +2339,8 @@
loadp CodeBlock::m_unlinkedCode[t2], t2
loadp UnlinkedCodeBlock::m_rareData[t2], t2
muli sizeof UnlinkedSimpleJumpTable, t3
- loadp UnlinkedCodeBlock::RareData::m_unlinkedSwitchJumpTables + FixedVector::m_storage + RefCountedArray::m_data[t2], t2
+ loadp UnlinkedCodeBlock::RareData::m_unlinkedSwitchJumpTables + UnlinkedSimpleJumpTableFixedVector::m_storage[t2], t2
+ addp (constexpr (UnlinkedSimpleJumpTableFixedVector::Storage::offsetOfData())), t2
addp t3, t2
btqnz t1, notCellMask, .opSwitchCharFallThrough
bbneq JSCell::m_type[t1], StringType, .opSwitchCharFallThrough
@@ -2353,10 +2355,10 @@
loadb [t1], t0
.opSwitchCharReady:
subi UnlinkedSimpleJumpTable::m_min[t2], t0
- loadp UnlinkedSimpleJumpTable::m_branchOffsets + FixedVector::m_storage + RefCountedArray::m_data[t2], t2
+ loadp UnlinkedSimpleJumpTable::m_branchOffsets + Int32FixedVector::m_storage[t2], t2
btpz t2, .opSwitchCharFallThrough
- biaeq t0, RefCountedArrayStorageNonNullSizeOffset[t2], .opSwitchCharFallThrough
- loadis [t2, t0, 4], t1
+ biaeq t0, Int32FixedVector::Storage::m_size[t2], .opSwitchCharFallThrough
+ loadis (constexpr (Int32FixedVector::Storage::offsetOfData()))[t2, t0, 4], t1
btiz t1, .opSwitchCharFallThrough
dispatchIndirect(t1)
Modified: trunk/Source/_javascript_Core/wasm/WasmCallee.h (287219 => 287220)
--- trunk/Source/_javascript_Core/wasm/WasmCallee.h 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/_javascript_Core/wasm/WasmCallee.h 2021-12-18 10:17:05 UTC (rev 287220)
@@ -37,6 +37,7 @@
#include "WasmLLIntTierUpCounter.h"
#include "WasmTierUpCount.h"
#include <wtf/FixedVector.h>
+#include <wtf/RefCountedFixedVector.h>
#include <wtf/ThreadSafeRefCounted.h>
namespace JSC {
@@ -264,32 +265,8 @@
MacroAssemblerCodePtr<WasmEntryPtrTag> m_entrypoint;
};
-class LLIntCallees : public ThreadSafeRefCounted<LLIntCallees> {
-public:
- static Ref<LLIntCallees> create(Vector<Ref<LLIntCallee>>&& llintCallees)
- {
- return adoptRef(*new LLIntCallees(WTFMove(llintCallees)));
- }
+using LLIntCallees = ThreadSafeRefCountedFixedVector<Ref<LLIntCallee>>;
- const Ref<LLIntCallee>& at(unsigned i) const
- {
- return m_llintCallees.at(i);
- }
-
- const Ref<LLIntCallee>* data() const
- {
- return m_llintCallees.data();
- }
-
-private:
- LLIntCallees(Vector<Ref<LLIntCallee>>&& llintCallees)
- : m_llintCallees(WTFMove(llintCallees))
- {
- }
-
- FixedVector<Ref<LLIntCallee>> m_llintCallees;
-};
-
} } // namespace JSC::Wasm
#endif // ENABLE(WEBASSEMBLY)
Modified: trunk/Source/_javascript_Core/wasm/WasmModule.cpp (287219 => 287220)
--- trunk/Source/_javascript_Core/wasm/WasmModule.cpp 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/_javascript_Core/wasm/WasmModule.cpp 2021-12-18 10:17:05 UTC (rev 287220)
@@ -36,7 +36,7 @@
Module::Module(LLIntPlan& plan)
: m_moduleInformation(plan.takeModuleInformation())
- , m_llintCallees(LLIntCallees::create(plan.takeCallees()))
+ , m_llintCallees(LLIntCallees::createFromVector(plan.takeCallees()))
, m_llintEntryThunks(plan.takeEntryThunks())
{
}
@@ -91,8 +91,8 @@
if (!calleeGroup || (calleeGroup->compilationFinished() && !calleeGroup->runnable())) {
RefPtr<LLIntCallees> llintCallees = nullptr;
if (Options::useWasmLLInt())
- llintCallees = m_llintCallees;
- calleeGroup = CalleeGroup::create(context, mode, const_cast<ModuleInformation&>(moduleInformation()), llintCallees);
+ llintCallees = m_llintCallees.copyRef();
+ calleeGroup = CalleeGroup::create(context, mode, const_cast<ModuleInformation&>(moduleInformation()), WTFMove(llintCallees));
m_calleeGroups[static_cast<uint8_t>(mode)] = calleeGroup;
}
return calleeGroup.releaseNonNull();
Modified: trunk/Source/_javascript_Core/wasm/WasmModule.h (287219 => 287220)
--- trunk/Source/_javascript_Core/wasm/WasmModule.h 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/_javascript_Core/wasm/WasmModule.h 2021-12-18 10:17:05 UTC (rev 287220)
@@ -74,7 +74,7 @@
Module(LLIntPlan&);
Ref<ModuleInformation> m_moduleInformation;
RefPtr<CalleeGroup> m_calleeGroups[Wasm::NumberOfMemoryModes];
- RefPtr<LLIntCallees> m_llintCallees;
+ Ref<LLIntCallees> m_llintCallees;
MacroAssemblerCodeRef<JITCompilationPtrTag> m_llintEntryThunks;
Lock m_lock;
};
Modified: trunk/Source/WTF/ChangeLog (287219 => 287220)
--- trunk/Source/WTF/ChangeLog 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/WTF/ChangeLog 2021-12-18 10:17:05 UTC (rev 287220)
@@ -1,3 +1,79 @@
+2021-12-17 Yusuke Suzuki <[email protected]>
+
+ [WTF] Introduce TrailingArray
+ https://bugs.webkit.org/show_bug.cgi?id=234201
+
+ Reviewed by Darin Adler.
+
+ This patch implements TrailingArray<Derived, T>, which allows us to implement class
+ with trailing array easily. By using this, we implement EmbeddedFixedVector and RefCountedFixedVector.
+ Plus, we replace underlying implementation of FixedVector from RefCountedArray to EmbeddedFixedVector
+ since ref-counting is not necessary. This is great for swapping: while RefCountedArray will decrease ref
+ and touching memory when destryoing, EmbeddedFixedVector does not, so we can keep memory untouched if
+ EmbeddedFixedVector's T is POD when destroying.
+
+ In a subsequent patch, we will remove RefCountedArray and use RefCountedFixedVector since RefCountedFixedVector
+ is following normal Ref / RefPtr protocol, so easy to understand the semantics.
+
+ * WTF.xcodeproj/project.pbxproj:
+ * wtf/CMakeLists.txt:
+ * wtf/EmbeddedFixedVector.h: Added.
+ * wtf/FixedVector.h:
+ (WTF::FixedVector::FixedVector):
+ (WTF::FixedVector::operator=):
+ (WTF::FixedVector::size const):
+ (WTF::FixedVector::isEmpty const):
+ (WTF::FixedVector::byteSize const):
+ (WTF::FixedVector::data):
+ (WTF::FixedVector::begin):
+ (WTF::FixedVector::end):
+ (WTF::FixedVector::rbegin):
+ (WTF::FixedVector::rend):
+ (WTF::FixedVector::rbegin const):
+ (WTF::FixedVector::rend const):
+ (WTF::FixedVector::at):
+ (WTF::FixedVector::at const):
+ (WTF::FixedVector::operator[]):
+ (WTF::FixedVector::operator[] const):
+ (WTF::FixedVector::fill):
+ (WTF::FixedVector::operator!= const):
+ (WTF::FixedVector::operator== const):
+ (WTF::FixedVector::swap):
+ (WTF::FixedVector::getStorage):
+ * wtf/RefCountedFixedVector.h: Added.
+ * wtf/TrailingArray.h: Added.
+ (WTF::TrailingArray::TrailingArray):
+ (WTF::TrailingArray::~TrailingArray):
+ (WTF::TrailingArray::allocationSize):
+ (WTF::TrailingArray::size const):
+ (WTF::TrailingArray::isEmpty const):
+ (WTF::TrailingArray::byteSize const):
+ (WTF::TrailingArray::data):
+ (WTF::TrailingArray::data const):
+ (WTF::TrailingArray::begin):
+ (WTF::TrailingArray::end):
+ (WTF::TrailingArray::begin const):
+ (WTF::TrailingArray::end const):
+ (WTF::TrailingArray::cbegin const):
+ (WTF::TrailingArray::cend const):
+ (WTF::TrailingArray::rbegin):
+ (WTF::TrailingArray::rend):
+ (WTF::TrailingArray::rbegin const):
+ (WTF::TrailingArray::rend const):
+ (WTF::TrailingArray::crbegin const):
+ (WTF::TrailingArray::crend const):
+ (WTF::TrailingArray::at):
+ (WTF::TrailingArray::at const):
+ (WTF::TrailingArray::operator[]):
+ (WTF::TrailingArray::operator[] const):
+ (WTF::TrailingArray::first):
+ (WTF::TrailingArray::first const):
+ (WTF::TrailingArray::last):
+ (WTF::TrailingArray::last const):
+ (WTF::TrailingArray::fill):
+ (WTF::TrailingArray::offsetOfSize):
+ (WTF::TrailingArray::offsetOfData):
+
2021-12-17 Sihui Liu <[email protected]>
Add custom copy() method for Ref<T> to CrossThreadCopier
Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (287219 => 287220)
--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj 2021-12-18 10:17:05 UTC (rev 287220)
@@ -758,6 +758,8 @@
E339C163244B4E8700359DA9 /* DataRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataRef.h; sourceTree = "<group>"; };
E33D5F871FBED66700BF625E /* RecursableLambda.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecursableLambda.h; sourceTree = "<group>"; };
E34CD0D022810A020020D299 /* Packed.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Packed.h; sourceTree = "<group>"; };
+ E3538D4C276220880075DA50 /* EmbeddedFixedVector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EmbeddedFixedVector.h; sourceTree = "<group>"; };
+ E3538D4D276220880075DA50 /* TrailingArray.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TrailingArray.h; sourceTree = "<group>"; };
E360C7642127B85B00C90F0E /* UnalignedAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnalignedAccess.h; sourceTree = "<group>"; };
E360C7652127B85C00C90F0E /* Unexpected.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Unexpected.h; sourceTree = "<group>"; };
E36895CB23A445CD008DD4C8 /* PackedRef.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PackedRef.h; sourceTree = "<group>"; };
@@ -781,6 +783,7 @@
E3E0F04F26197157004640FC /* FixedVector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FixedVector.h; sourceTree = "<group>"; };
E3E158251EADA53C004A079D /* SystemFree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SystemFree.h; sourceTree = "<group>"; };
E3E64F0B22813428001E55B4 /* Nonmovable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Nonmovable.h; sourceTree = "<group>"; };
+ E3E8162F2764799300BAA45B /* RefCountedFixedVector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RefCountedFixedVector.h; sourceTree = "<group>"; };
E419F2E623AB9E2300B26129 /* VectorHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VectorHash.h; sourceTree = "<group>"; };
E431CC4A21187ADB000C8A07 /* DispatchSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DispatchSPI.h; sourceTree = "<group>"; };
E4A0AD371A96245500536DF6 /* WorkQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkQueue.cpp; sourceTree = "<group>"; };
@@ -1071,6 +1074,7 @@
A8A47280151A825A004123FF /* DoublyLinkedList.h */,
A8A47297151A825A004123FF /* dtoa.cpp */,
A8A47298151A825A004123FF /* dtoa.h */,
+ E3538D4C276220880075DA50 /* EmbeddedFixedVector.h */,
5338EBA423AB04D100382662 /* EnumClassOperatorOverloads.h */,
1AEA88E11D6BBCF400E5AD64 /* EnumTraits.h */,
AD7C434A1DD2A4A70026888B /* Expected.h */,
@@ -1267,6 +1271,7 @@
A8A472FF151A825B004123FF /* RefCounted.h */,
0FA6F39020CC61EB00A03DCD /* RefCountedArray.cpp */,
A8A47300151A825B004123FF /* RefCountedArray.h */,
+ E3E8162F2764799300BAA45B /* RefCountedFixedVector.h */,
A8A47301151A825B004123FF /* RefCountedLeakCounter.cpp */,
A8A47302151A825B004123FF /* RefCountedLeakCounter.h */,
86F46F5F1A2840EE00CCBF22 /* RefCounter.h */,
@@ -1357,6 +1362,7 @@
0F7075F31FBF537A00489AF0 /* TimingScope.h */,
553071C91C40427200384898 /* TinyLRUCache.h */,
0FED67B51B22D4D80066CE15 /* TinyPtrSet.h */,
+ E3538D4D276220880075DA50 /* TrailingArray.h */,
521CC6B324A277C2004377D6 /* TranslatedProcess.cpp */,
2D1F2F462498F73300C63A83 /* TranslatedProcess.h */,
149EF16216BBFE0D000A4331 /* TriState.h */,
Modified: trunk/Source/WTF/wtf/CMakeLists.txt (287219 => 287220)
--- trunk/Source/WTF/wtf/CMakeLists.txt 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/WTF/wtf/CMakeLists.txt 2021-12-18 10:17:05 UTC (rev 287220)
@@ -62,6 +62,7 @@
DisallowCType.h
Dominators.h
DoublyLinkedList.h
+ EmbeddedFixedVector.h
EnumClassOperatorOverloads.h
EnumTraits.h
Expected.h
@@ -219,6 +220,7 @@
Ref.h
RefCounted.h
RefCountedArray.h
+ RefCountedFixedVector.h
RefCountedLeakCounter.h
RefCounter.h
RefPtr.h
@@ -289,6 +291,7 @@
TimingScope.h
TinyLRUCache.h
TinyPtrSet.h
+ TrailingArray.h
TranslatedProcess.h
TriState.h
TypeCasts.h
Added: trunk/Source/WTF/wtf/EmbeddedFixedVector.h (0 => 287220)
--- trunk/Source/WTF/wtf/EmbeddedFixedVector.h (rev 0)
+++ trunk/Source/WTF/wtf/EmbeddedFixedVector.h 2021-12-18 10:17:05 UTC (rev 287220)
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <wtf/Noncopyable.h>
+#include <wtf/Nonmovable.h>
+#include <wtf/TrailingArray.h>
+#include <wtf/UniqueRef.h>
+
+namespace WTF {
+
+template<typename T>
+class EmbeddedFixedVector final : public TrailingArray<EmbeddedFixedVector<T>, T> {
+ WTF_MAKE_FAST_ALLOCATED(EmbeddedFixedVector);
+ WTF_MAKE_NONCOPYABLE(EmbeddedFixedVector);
+ WTF_MAKE_NONMOVABLE(EmbeddedFixedVector);
+public:
+ using Base = TrailingArray<EmbeddedFixedVector<T>, T>;
+
+ static UniqueRef<EmbeddedFixedVector> create(unsigned size)
+ {
+ return UniqueRef { *new (NotNull, fastMalloc(Base::allocationSize(size))) EmbeddedFixedVector(size) };
+ }
+
+ template<typename InputIterator>
+ static UniqueRef<EmbeddedFixedVector> create(InputIterator first, InputIterator last)
+ {
+ unsigned size = Checked<uint32_t> { std::distance(first, last) };
+ return UniqueRef { *new (NotNull, fastMalloc(Base::allocationSize(size))) EmbeddedFixedVector(size, first, last) };
+ }
+
+ template<size_t inlineCapacity, typename OverflowHandler>
+ static UniqueRef<EmbeddedFixedVector> createFromVector(const Vector<T, inlineCapacity, OverflowHandler>& other)
+ {
+ unsigned size = Checked<uint32_t> { other.size() }.value();
+ return UniqueRef { *new (NotNull, fastMalloc(Base::allocationSize(size))) EmbeddedFixedVector(size, other.begin(), other.end()) };
+ }
+
+ template<size_t inlineCapacity, typename OverflowHandler>
+ static UniqueRef<EmbeddedFixedVector> createFromVector(Vector<T, inlineCapacity, OverflowHandler>&& other)
+ {
+ Vector<T, inlineCapacity, OverflowHandler> container = WTFMove(other);
+ unsigned size = Checked<uint32_t> { container.size() }.value();
+ return UniqueRef { *new (NotNull, fastMalloc(Base::allocationSize(size))) EmbeddedFixedVector(size, std::move_iterator { container.begin() }, std::move_iterator { container.end() }) };
+ }
+
+ UniqueRef<EmbeddedFixedVector> clone() const
+ {
+ return create(Base::begin(), Base::end());
+ }
+
+ bool operator!=(const EmbeddedFixedVector& other) const
+ {
+ return !(*this == other);
+ }
+
+ bool operator==(const EmbeddedFixedVector& other) const
+ {
+ if (Base::size() != other.size())
+ return false;
+ for (unsigned i = 0; i < Base::size(); ++i) {
+ if (Base::at(i) != other.at(i))
+ return false;
+ }
+ return true;
+ }
+
+private:
+ explicit EmbeddedFixedVector(unsigned size)
+ : Base(size)
+ {
+ }
+
+ template<typename InputIterator>
+ EmbeddedFixedVector(unsigned size, InputIterator first, InputIterator last)
+ : Base(size, first, last)
+ {
+ }
+};
+
+} // namespace WTF
+
+using WTF::EmbeddedFixedVector;
Modified: trunk/Source/WTF/wtf/FixedVector.h (287219 => 287220)
--- trunk/Source/WTF/wtf/FixedVector.h 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Source/WTF/wtf/FixedVector.h 2021-12-18 10:17:05 UTC (rev 287220)
@@ -25,6 +25,7 @@
#pragma once
+#include <wtf/EmbeddedFixedVector.h>
#include <wtf/RefCountedArray.h>
namespace WTF {
@@ -34,6 +35,7 @@
template<typename T>
class FixedVector {
public:
+ using Storage = EmbeddedFixedVector<T>;
using iterator = T*;
using const_iterator = const T*;
using reverse_iterator = std::reverse_iterator<iterator>;
@@ -41,7 +43,7 @@
FixedVector() = default;
FixedVector(const FixedVector& other)
- : m_storage(other.m_storage.clone())
+ : m_storage(other.m_storage ? other.m_storage->clone().moveToUniquePtr() : nullptr)
{ }
FixedVector(FixedVector&& other) = default;
@@ -60,55 +62,58 @@
}
explicit FixedVector(size_t size)
- : m_storage(size)
+ : m_storage(size ? Storage::create(size).moveToUniquePtr() : nullptr)
{ }
template<size_t inlineCapacity, typename OverflowHandler>
explicit FixedVector(const Vector<T, inlineCapacity, OverflowHandler>& other)
- : m_storage(other)
+ : m_storage(other.isEmpty() ? nullptr : Storage::createFromVector(other).moveToUniquePtr())
{ }
template<size_t inlineCapacity, typename OverflowHandler>
FixedVector& operator=(const Vector<T, inlineCapacity, OverflowHandler>& other)
{
- m_storage = other;
+ m_storage = other.isEmpty() ? nullptr : Storage::createFromVector(other).moveToUniquePtr();
return *this;
}
template<size_t inlineCapacity, typename OverflowHandler>
explicit FixedVector(Vector<T, inlineCapacity, OverflowHandler>&& other)
- : m_storage(WTFMove(other))
- { }
+ {
+ Vector<T, inlineCapacity, OverflowHandler> target = WTFMove(other);
+ m_storage = target.isEmpty() ? nullptr : Storage::createFromVector(WTFMove(target)).moveToUniquePtr();
+ }
template<size_t inlineCapacity, typename OverflowHandler>
FixedVector& operator=(Vector<T, inlineCapacity, OverflowHandler>&& other)
{
- m_storage = WTFMove(other);
+ Vector<T, inlineCapacity, OverflowHandler> target = WTFMove(other);
+ m_storage = target.isEmpty() ? nullptr : Storage::createFromVector(WTFMove(target)).moveToUniquePtr();
return *this;
}
- size_t size() const { return m_storage.size(); }
- bool isEmpty() const { return m_storage.isEmpty(); }
- size_t byteSize() const { return m_storage.byteSize(); }
+ size_t size() const { return m_storage ? m_storage->size() : 0; }
+ bool isEmpty() const { return m_storage ? m_storage->isEmpty() : true; }
+ size_t byteSize() const { return m_storage ? m_storage->byteSize() : 0; }
- T* data() { return m_storage.data(); }
- iterator begin() { return m_storage.begin(); }
- iterator end() { return m_storage.end(); }
+ T* data() { return m_storage ? m_storage->data() : nullptr; }
+ iterator begin() { return m_storage ? m_storage->begin() : nullptr; }
+ iterator end() { return m_storage ? m_storage->end() : nullptr; }
const T* data() const { return const_cast<FixedVector*>(this)->data(); }
const_iterator begin() const { return const_cast<FixedVector*>(this)->begin(); }
const_iterator end() const { return const_cast<FixedVector*>(this)->end(); }
- reverse_iterator rbegin() { return m_storage.rbegin(); }
- reverse_iterator rend() { return m_storage.rend(); }
- const_reverse_iterator rbegin() const { return m_storage.rbegin(); }
- const_reverse_iterator rend() const { return m_storage.rend(); }
+ reverse_iterator rbegin() { return m_storage ? m_storage->rbegin() : reverse_iterator(nullptr); }
+ reverse_iterator rend() { return m_storage ? m_storage->rend() : reverse_iterator(nullptr); }
+ const_reverse_iterator rbegin() const { return m_storage ? m_storage->rbegin() : const_reverse_iterator(nullptr); }
+ const_reverse_iterator rend() const { return m_storage ? m_storage->rend() : const_reverse_iterator(nullptr); }
- T& at(size_t i) { return m_storage.at(i); }
- const T& at(size_t i) const { return m_storage.at(i); }
+ T& at(size_t i) { return m_storage->at(i); }
+ const T& at(size_t i) const { return m_storage->at(i); }
- T& operator[](size_t i) { return at(i); }
- const T& operator[](size_t i) const { return at(i); }
+ T& operator[](size_t i) { return m_storage->at(i); }
+ const T& operator[](size_t i) const { return m_storage->at(i); }
T& first() { return (*this)[0]; }
const T& first() const { return (*this)[0]; }
@@ -115,21 +120,44 @@
T& last() { return (*this)[size() - 1]; }
const T& last() const { return (*this)[size() - 1]; }
- void fill(const T& val) { m_storage.fill(val); }
+ void fill(const T& val)
+ {
+ if (!m_storage)
+ return;
+ m_storage->fill(val);
+ }
- bool operator==(const FixedVector<T>& other) const { return m_storage == other.m_storage; }
+ bool operator!=(const FixedVector<T>& other) const
+ {
+ return !(*this == other);
+ }
+ bool operator==(const FixedVector<T>& other) const
+ {
+ if (!m_storage) {
+ if (!other.m_storage)
+ return true;
+ return other.m_storage->isEmpty();
+ }
+ if (!other.m_storage)
+ return m_storage->isEmpty();
+ return *m_storage == *other.m_storage;
+ }
+
void swap(FixedVector<T>& other)
{
- m_storage.swap(other.m_storage);
+ using std::swap;
+ swap(m_storage, other.m_storage);
}
static ptrdiff_t offsetOfStorage() { return OBJECT_OFFSETOF(FixedVector, m_storage); }
+ Storage* storage() { return m_storage.get(); }
+
private:
friend class JSC::LLIntOffsetsExtractor;
- RefCountedArray<T> m_storage;
+ std::unique_ptr<Storage> m_storage;
};
static_assert(sizeof(FixedVector<int>) == sizeof(int*));
Added: trunk/Source/WTF/wtf/RefCountedFixedVector.h (0 => 287220)
--- trunk/Source/WTF/wtf/RefCountedFixedVector.h (rev 0)
+++ trunk/Source/WTF/wtf/RefCountedFixedVector.h 2021-12-18 10:17:05 UTC (rev 287220)
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <type_traits>
+#include <wtf/Ref.h>
+#include <wtf/RefCounted.h>
+#include <wtf/ThreadSafeRefCounted.h>
+#include <wtf/TrailingArray.h>
+
+namespace WTF {
+
+template<typename T, bool isThreadSafe>
+class RefCountedFixedVectorBase final : public std::conditional<isThreadSafe, ThreadSafeRefCounted<RefCountedFixedVectorBase<T, isThreadSafe>>, RefCounted<RefCountedFixedVectorBase<T, isThreadSafe>>>::type, public TrailingArray<RefCountedFixedVectorBase<T, isThreadSafe>, T> {
+public:
+ using Base = TrailingArray<RefCountedFixedVectorBase<T, isThreadSafe>, T>;
+
+ static Ref<RefCountedFixedVectorBase> create(unsigned size)
+ {
+ return adoptRef(*new (NotNull, fastMalloc(Base::allocationSize(size))) RefCountedFixedVectorBase(size));
+ }
+
+ template<typename InputIterator>
+ static Ref<RefCountedFixedVectorBase> create(InputIterator first, InputIterator last)
+ {
+ unsigned size = Checked<uint32_t> { std::distance(first, last) };
+ return adoptRef(*new (NotNull, fastMalloc(Base::allocationSize(size))) RefCountedFixedVectorBase(size, first, last));
+ }
+
+ template<size_t inlineCapacity, typename OverflowHandler>
+ static Ref<RefCountedFixedVectorBase> createFromVector(const Vector<T, inlineCapacity, OverflowHandler>& other)
+ {
+ unsigned size = Checked<uint32_t> { other.size() }.value();
+ return adoptRef(*new (NotNull, fastMalloc(Base::allocationSize(size))) RefCountedFixedVectorBase(size, std::begin(other), std::end(other)));
+ }
+
+ template<size_t inlineCapacity, typename OverflowHandler>
+ static Ref<RefCountedFixedVectorBase> createFromVector(Vector<T, inlineCapacity, OverflowHandler>&& other)
+ {
+ Vector<T, inlineCapacity, OverflowHandler> container = WTFMove(other);
+ unsigned size = Checked<uint32_t> { container.size() }.value();
+ return adoptRef(*new (NotNull, fastMalloc(Base::allocationSize(size))) RefCountedFixedVectorBase(size, std::move_iterator { container.begin() }, std::move_iterator { container.end() }));
+ }
+
+ Ref<RefCountedFixedVectorBase> clone() const
+ {
+ return create(Base::begin(), Base::end());
+ }
+
+ bool operator!=(const RefCountedFixedVectorBase& other) const
+ {
+ return !(*this == other);
+ }
+
+ bool operator==(const RefCountedFixedVectorBase& other) const
+ {
+ if (Base::size() != other.size())
+ return false;
+ for (unsigned i = 0; i < Base::size(); ++i) {
+ if (Base::at(i) != other.at(i))
+ return false;
+ }
+ return true;
+ }
+
+private:
+ explicit RefCountedFixedVectorBase(unsigned size)
+ : Base(size)
+ {
+ }
+
+ template<typename InputIterator>
+ RefCountedFixedVectorBase(unsigned size, InputIterator first, InputIterator last)
+ : Base(size, first, last)
+ {
+ }
+};
+
+template<typename T>
+using RefCountedFixedVector = RefCountedFixedVectorBase<T, false>;
+template<typename T>
+using ThreadSafeRefCountedFixedVector = RefCountedFixedVectorBase<T, true>;
+
+} // namespace WTF
+
+using WTF::RefCountedFixedVector;
+using WTF::ThreadSafeRefCountedFixedVector;
Added: trunk/Source/WTF/wtf/TrailingArray.h (0 => 287220)
--- trunk/Source/WTF/wtf/TrailingArray.h (rev 0)
+++ trunk/Source/WTF/wtf/TrailingArray.h 2021-12-18 10:17:05 UTC (rev 287220)
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <type_traits>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+
+namespace WTF {
+
+// TrailingArray offers the feature trailing array in the derived class.
+// We can allocate a memory like the following layout.
+//
+// [ DerivedClass ][ Trailing Array ]
+//
+// And trailing array offers appropriate methods for accessing and destructions.
+template<typename Derived, typename T>
+class TrailingArray {
+ WTF_MAKE_NONCOPYABLE(TrailingArray);
+ friend class JSC::LLIntOffsetsExtractor;
+public:
+ using value_type = T;
+ using pointer = T*;
+ using reference = T&;
+ using const_reference = const T&;
+ using const_pointer = const T*;
+ using size_type = unsigned;
+ using difference_type = std::make_signed_t<size_type>;
+ using iterator = T*;
+ using const_iterator = const T*;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ explicit TrailingArray(unsigned size)
+ : m_size(size)
+ {
+ static_assert(std::is_final_v<Derived>);
+ VectorTypeOperations<T>::initializeIfNonPOD(begin(), end());
+ }
+
+ template<typename InputIterator>
+ TrailingArray(unsigned size, InputIterator first, InputIterator last)
+ : m_size(size)
+ {
+ static_assert(std::is_final_v<Derived>);
+ ASSERT(std::distance(first, last) == size);
+ std::uninitialized_copy(first, last, begin());
+ }
+
+ ~TrailingArray()
+ {
+ VectorTypeOperations<T>::destruct(begin(), end());
+ }
+
+ static constexpr size_t allocationSize(unsigned size)
+ {
+ return offsetOfData() + size * sizeof(T);
+ }
+
+ unsigned size() const { return m_size; }
+ bool isEmpty() const { return !size(); }
+ unsigned byteSize() const { return size() * sizeof(T); }
+
+ pointer data() { return bitwise_cast<T*>(bitwise_cast<uint8_t*>(static_cast<Derived*>(this)) + offsetOfData()); }
+ const_pointer data() const { return bitwise_cast<const T*>(bitwise_cast<const uint8_t*>(static_cast<const Derived*>(this)) + offsetOfData()); }
+
+ iterator begin() { return data(); }
+ iterator end() { return data() + size(); }
+ const_iterator begin() const { return cbegin(); }
+ const_iterator end() const { return cend(); }
+ const_iterator cbegin() const { return data(); }
+ const_iterator cend() const { return data() + size(); }
+
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rbegin() const { return crbegin(); }
+ const_reverse_iterator rend() const { return crend(); }
+ const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
+ const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
+
+ reference at(unsigned i)
+ {
+ ASSERT(i < size());
+ return begin()[i];
+ }
+
+ const_reference at(unsigned i) const
+ {
+ ASSERT(i < size());
+ return begin()[i];
+ }
+
+ reference operator[](unsigned i) { return at(i); }
+ const_reference operator[](unsigned i) const { return at(i); }
+
+ T& first() { return (*this)[0]; }
+ const T& first() const { return (*this)[0]; }
+ T& last() { return (*this)[size() - 1]; }
+ const T& last() const { return (*this)[size() - 1]; }
+
+ void fill(const T& val)
+ {
+ std::fill(begin(), end(), val);
+ }
+
+ static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(Derived, m_size); }
+ static constexpr ptrdiff_t offsetOfData()
+ {
+ return WTF::roundUpToMultipleOf<alignof(T)>(sizeof(Derived));
+ }
+
+protected:
+ unsigned m_size { 0 };
+};
+
+} // namespace WTF
+
+using WTF::TrailingArray;
Modified: trunk/Tools/ChangeLog (287219 => 287220)
--- trunk/Tools/ChangeLog 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Tools/ChangeLog 2021-12-18 10:17:05 UTC (rev 287220)
@@ -1,5 +1,27 @@
2021-12-17 Yusuke Suzuki <[email protected]>
+ [WTF] Introduce TrailingArray
+ https://bugs.webkit.org/show_bug.cgi?id=234201
+
+ Reviewed by Darin Adler.
+
+ * TestWebKitAPI/CMakeLists.txt:
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WTF/EmbeddedFixedVector.cpp: Added.
+ (TestWebKitAPI::TEST):
+ (TestWebKitAPI::DestructorObserver::DestructorObserver):
+ (TestWebKitAPI::DestructorObserver::~DestructorObserver):
+ (TestWebKitAPI::DestructorObserver::operator=):
+ * TestWebKitAPI/Tests/WTF/FixedVector.cpp:
+ (TestWebKitAPI::TEST):
+ * TestWebKitAPI/Tests/WTF/RefCountedFixedVector.cpp: Added.
+ (TestWebKitAPI::TEST):
+ (TestWebKitAPI::DestructorObserver::DestructorObserver):
+ (TestWebKitAPI::DestructorObserver::~DestructorObserver):
+ (TestWebKitAPI::DestructorObserver::operator=):
+
+2021-12-17 Yusuke Suzuki <[email protected]>
+
[JSC] Fix runscript's standalone ability to run
https://bugs.webkit.org/show_bug.cgi?id=234166
Modified: trunk/Tools/TestWebKitAPI/CMakeLists.txt (287219 => 287220)
--- trunk/Tools/TestWebKitAPI/CMakeLists.txt 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Tools/TestWebKitAPI/CMakeLists.txt 2021-12-18 10:17:05 UTC (rev 287220)
@@ -38,6 +38,7 @@
Tests/WTF/DataMutex.cpp
Tests/WTF/DateMath.cpp
Tests/WTF/Deque.cpp
+ Tests/WTF/EmbeddedFixedVector.cpp
Tests/WTF/EnumTraits.cpp
Tests/WTF/Expected.cpp
Tests/WTF/FileSystem.cpp
@@ -74,6 +75,7 @@
Tests/WTF/PriorityQueue.cpp
Tests/WTF/RedBlackTree.cpp
Tests/WTF/Ref.cpp
+ Tests/WTF/RefCountedFixedVector.cpp
Tests/WTF/RefCounter.cpp
Tests/WTF/RefLogger.cpp
Tests/WTF/RefPtr.cpp
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (287219 => 287220)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2021-12-18 10:17:05 UTC (rev 287220)
@@ -966,6 +966,7 @@
E1220DCA155B28AA0013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = E1220DC9155B287D0013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.html */; };
E194E1BD177E53C7009C4D4E /* StopLoadingFromDidReceiveResponse.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = E194E1BC177E534A009C4D4E /* StopLoadingFromDidReceiveResponse.html */; };
E302BDAA2404B92400865277 /* CompactRefPtrTuple.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E302BDA92404B92300865277 /* CompactRefPtrTuple.cpp */; };
+ E316D42027647A0200287B16 /* RefCountedFixedVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E316D41F27647A0200287B16 /* RefCountedFixedVector.cpp */; };
E3210519261979F300157C67 /* FixedVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3210518261979F300157C67 /* FixedVector.cpp */; };
E324A6F02041C82000A76593 /* UniqueArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E398BC0F2041C76300387136 /* UniqueArray.cpp */; };
E325C90723E3870200BC7D3B /* PictureInPictureSupport.mm in Sources */ = {isa = PBXBuildFile; fileRef = E325C90623E3870200BC7D3B /* PictureInPictureSupport.mm */; };
@@ -975,6 +976,7 @@
E355A6322615718F001C1129 /* RobinHoodHashMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E355A6312615718F001C1129 /* RobinHoodHashMap.cpp */; };
E35B908223F60DD0000011FF /* LocalizedDeviceModel.mm in Sources */ = {isa = PBXBuildFile; fileRef = E35B908123F60DD0000011FF /* LocalizedDeviceModel.mm */; };
E35FC7B222B82A7300F32F98 /* JSLockTakesWebThreadLock.mm in Sources */ = {isa = PBXBuildFile; fileRef = E35FC7B122B82A6D00F32F98 /* JSLockTakesWebThreadLock.mm */; };
+ E36B87A3276221870059D2F9 /* EmbeddedFixedVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E36B87A2276221860059D2F9 /* EmbeddedFixedVector.cpp */; };
E373D7911F2CF35200C6FAAF /* Signals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3953F951F2CF32100A76A2E /* Signals.cpp */; };
E38A0D351FD50CC300E98C8B /* Threading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38A0D341FD50CBC00E98C8B /* Threading.cpp */; };
E38D65CA23A45FAA0063D69A /* PackedRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38D65C823A45FA90063D69A /* PackedRef.cpp */; };
@@ -2890,6 +2892,7 @@
E194E1BA177E5145009C4D4E /* StopLoadingFromDidReceiveResponse.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = StopLoadingFromDidReceiveResponse.mm; sourceTree = "<group>"; };
E194E1BC177E534A009C4D4E /* StopLoadingFromDidReceiveResponse.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = StopLoadingFromDidReceiveResponse.html; sourceTree = "<group>"; };
E302BDA92404B92300865277 /* CompactRefPtrTuple.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompactRefPtrTuple.cpp; sourceTree = "<group>"; };
+ E316D41F27647A0200287B16 /* RefCountedFixedVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RefCountedFixedVector.cpp; sourceTree = "<group>"; };
E3210518261979F300157C67 /* FixedVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FixedVector.cpp; sourceTree = "<group>"; };
E325C90623E3870200BC7D3B /* PictureInPictureSupport.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PictureInPictureSupport.mm; sourceTree = "<group>"; };
E32B549122810AC0008AD702 /* Packed.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Packed.cpp; sourceTree = "<group>"; };
@@ -2898,6 +2901,7 @@
E355A6312615718F001C1129 /* RobinHoodHashMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RobinHoodHashMap.cpp; sourceTree = "<group>"; };
E35B908123F60DD0000011FF /* LocalizedDeviceModel.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = LocalizedDeviceModel.mm; sourceTree = "<group>"; };
E35FC7B122B82A6D00F32F98 /* JSLockTakesWebThreadLock.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = JSLockTakesWebThreadLock.mm; sourceTree = "<group>"; };
+ E36B87A2276221860059D2F9 /* EmbeddedFixedVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EmbeddedFixedVector.cpp; sourceTree = "<group>"; };
E388887020C9098100E632BC /* WorkerPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkerPool.cpp; sourceTree = "<group>"; };
E38A0D341FD50CBC00E98C8B /* Threading.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Threading.cpp; sourceTree = "<group>"; };
E38D65C823A45FA90063D69A /* PackedRef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PackedRef.cpp; sourceTree = "<group>"; };
@@ -4484,6 +4488,7 @@
7AA021BA1AB09EA70052953F /* DateMath.cpp */,
1A3524A91D627BD40031729B /* DeletedAddressOfOperator.h */,
E4A757D3178AEA5B00B5D7A4 /* Deque.cpp */,
+ E36B87A2276221860059D2F9 /* EmbeddedFixedVector.cpp */,
1AF7B21D1D6CD12E008C126C /* EnumTraits.cpp */,
AD7C434C1DD2A5470026888B /* Expected.cpp */,
A310827121F296EC00C28B97 /* FileSystem.cpp */,
@@ -4526,6 +4531,7 @@
53EC253F1E96BC80000831B9 /* PriorityQueue.cpp */,
0FC6C4CB141027E0005B7F0C /* RedBlackTree.cpp */,
93A427AA180DA26400CD24D7 /* Ref.cpp */,
+ E316D41F27647A0200287B16 /* RefCountedFixedVector.cpp */,
86BD19971A2DB05B006DCF0A /* RefCounter.cpp */,
442BBF681C91CAD90017087F /* RefLogger.cpp */,
93A427AD180DA60F00CD24D7 /* RefLogger.h */,
@@ -5265,6 +5271,7 @@
5C2C01A82734883600F89D37 /* CrossThreadCopier.cpp in Sources */,
7C83DEA91D0A590C00FEBCF3 /* CString.cpp in Sources */,
7C83DEAD1D0A590C00FEBCF3 /* Deque.cpp in Sources */,
+ E36B87A3276221870059D2F9 /* EmbeddedFixedVector.cpp in Sources */,
1AF7B21F1D6CD14D008C126C /* EnumTraits.cpp in Sources */,
AD7C434D1DD2A54E0026888B /* Expected.cpp in Sources */,
A310827221F296FF00C28B97 /* FileSystem.cpp in Sources */,
@@ -5306,6 +5313,7 @@
53EC25411E96FD87000831B9 /* PriorityQueue.cpp in Sources */,
7C83DF131D0A590C00FEBCF3 /* RedBlackTree.cpp in Sources */,
7C83DF141D0A590C00FEBCF3 /* Ref.cpp in Sources */,
+ E316D42027647A0200287B16 /* RefCountedFixedVector.cpp in Sources */,
7C83DF151D0A590C00FEBCF3 /* RefCounter.cpp in Sources */,
7C83DED71D0A590C00FEBCF3 /* RefLogger.cpp in Sources */,
7C83DF161D0A590C00FEBCF3 /* RefPtr.cpp in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WTF/EmbeddedFixedVector.cpp (0 => 287220)
--- trunk/Tools/TestWebKitAPI/Tests/WTF/EmbeddedFixedVector.cpp (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/EmbeddedFixedVector.cpp 2021-12-18 10:17:05 UTC (rev 287220)
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+
+#include "MoveOnly.h"
+#include <wtf/EmbeddedFixedVector.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF_EmbeddedFixedVector, Empty)
+{
+ auto vector = EmbeddedFixedVector<unsigned>::create(0);
+ EXPECT_TRUE(vector->isEmpty());
+ EXPECT_EQ(0U, vector->size());
+}
+
+TEST(WTF_EmbeddedFixedVector, Iterator)
+{
+ auto intVector = EmbeddedFixedVector<unsigned>::create(4);
+ intVector.get()[0] = 10;
+ intVector.get()[1] = 11;
+ intVector.get()[2] = 12;
+ intVector.get()[3] = 13;
+
+ auto it = intVector->begin();
+ auto end = intVector->end();
+ EXPECT_TRUE(end != it);
+
+ EXPECT_EQ(10U, *it);
+ ++it;
+ EXPECT_EQ(11U, *it);
+ ++it;
+ EXPECT_EQ(12U, *it);
+ ++it;
+ EXPECT_EQ(13U, *it);
+ ++it;
+
+ EXPECT_TRUE(end == it);
+}
+
+TEST(WTF_EmbeddedFixedVector, OverloadedOperatorAmpersand)
+{
+ struct Test {
+ private:
+ Test* operator&() = delete;
+ };
+
+ auto vector = EmbeddedFixedVector<Test>::create(1);
+ vector.get()[0] = Test();
+}
+
+TEST(WTF_EmbeddedFixedVector, Copy)
+{
+ auto vec1 = EmbeddedFixedVector<unsigned>::create(3);
+ vec1.get()[0] = 0;
+ vec1.get()[1] = 1;
+ vec1.get()[2] = 2;
+
+ auto vec2 = EmbeddedFixedVector<unsigned>::create(vec1->begin(), vec1->end());
+ EXPECT_EQ(3U, vec1->size());
+ EXPECT_EQ(3U, vec2->size());
+ for (unsigned i = 0; i < vec1->size(); ++i) {
+ EXPECT_EQ(i, vec1.get()[i]);
+ EXPECT_EQ(i, vec2.get()[i]);
+ }
+ vec1.get()[2] = 42;
+ EXPECT_EQ(42U, vec1.get()[2]);
+ EXPECT_EQ(2U, vec2.get()[2]);
+}
+
+TEST(WTF_EmbeddedFixedVector, CopyVector)
+{
+ auto vec1 = Vector<unsigned>::from(0, 1, 2, 3);
+ EXPECT_EQ(4U, vec1.size());
+ auto vec2 = EmbeddedFixedVector<unsigned>::createFromVector(vec1);
+ EXPECT_EQ(4U, vec1.size());
+ EXPECT_EQ(4U, vec2->size());
+ for (unsigned i = 0; i < vec1.size(); ++i) {
+ EXPECT_EQ(i, vec1[i]);
+ EXPECT_EQ(i, vec2.get()[i]);
+ }
+ vec1[2] = 42;
+ EXPECT_EQ(42U, vec1[2]);
+ EXPECT_EQ(2U, vec2.get()[2]);
+}
+
+TEST(WTF_EmbeddedFixedVector, MoveVector)
+{
+ auto vec1 = Vector<MoveOnly>::from(MoveOnly(0), MoveOnly(1), MoveOnly(2), MoveOnly(3));
+ EXPECT_EQ(4U, vec1.size());
+ auto vec2 = EmbeddedFixedVector<MoveOnly>::createFromVector(WTFMove(vec1));
+ EXPECT_EQ(0U, vec1.size());
+ EXPECT_EQ(4U, vec2->size());
+ for (unsigned index = 0; index < vec2->size(); ++index)
+ EXPECT_EQ(index, vec2.get()[index].value());
+}
+
+TEST(WTF_EmbeddedFixedVector, IteratorFor)
+{
+ auto vec1 = EmbeddedFixedVector<unsigned>::create(3);
+ vec1.get()[0] = 0;
+ vec1.get()[1] = 1;
+ vec1.get()[2] = 2;
+
+ unsigned index = 0;
+ for (auto iter = vec1->begin(); iter != vec1->end(); ++iter) {
+ EXPECT_EQ(index, *iter);
+ ++index;
+ }
+}
+
+TEST(WTF_EmbeddedFixedVector, Reverse)
+{
+ auto vec1 = EmbeddedFixedVector<unsigned>::create(3);
+ vec1.get()[0] = 0;
+ vec1.get()[1] = 1;
+ vec1.get()[2] = 2;
+
+ unsigned index = 0;
+ for (auto iter = vec1->rbegin(); iter != vec1->rend(); ++iter) {
+ ++index;
+ EXPECT_EQ(3U - index, *iter);
+ }
+}
+
+TEST(WTF_EmbeddedFixedVector, Fill)
+{
+ auto vec1 = EmbeddedFixedVector<unsigned>::create(3);
+ vec1->fill(42);
+
+ for (auto& value : vec1.get())
+ EXPECT_EQ(42U, value);
+}
+
+struct DestructorObserver {
+ DestructorObserver() = default;
+
+ DestructorObserver(bool* destructed)
+ : destructed(destructed)
+ {
+ }
+
+ ~DestructorObserver()
+ {
+ if (destructed)
+ *destructed = true;
+ }
+
+ DestructorObserver(DestructorObserver&& other)
+ : destructed(other.destructed)
+ {
+ other.destructed = nullptr;
+ }
+
+ DestructorObserver& operator=(DestructorObserver&& other)
+ {
+ destructed = other.destructed;
+ other.destructed = nullptr;
+ return *this;
+ }
+
+ bool* destructed { nullptr };
+};
+
+TEST(WTF_EmbeddedFixedVector, Destructor)
+{
+ Vector<bool> flags(3, false);
+ {
+ auto vector = EmbeddedFixedVector<DestructorObserver>::create(flags.size());
+ for (unsigned i = 0; i < flags.size(); ++i)
+ vector.get()[i] = DestructorObserver(&flags[i]);
+ for (unsigned i = 0; i < flags.size(); ++i)
+ EXPECT_FALSE(flags[i]);
+ }
+ for (unsigned i = 0; i < flags.size(); ++i)
+ EXPECT_TRUE(flags[i]);
+}
+
+TEST(WTF_EmbeddedFixedVector, DestructorAfterMove)
+{
+ Vector<bool> flags(3, false);
+ {
+ std::unique_ptr<EmbeddedFixedVector<DestructorObserver>> outerVector;
+ {
+ auto vector = EmbeddedFixedVector<DestructorObserver>::create(flags.size());
+ for (unsigned i = 0; i < flags.size(); ++i)
+ vector.get()[i] = DestructorObserver(&flags[i]);
+ for (unsigned i = 0; i < flags.size(); ++i)
+ EXPECT_FALSE(flags[i]);
+ outerVector = vector.moveToUniquePtr();
+ }
+ for (unsigned i = 0; i < flags.size(); ++i)
+ EXPECT_FALSE(flags[i]);
+ }
+ for (unsigned i = 0; i < flags.size(); ++i)
+ EXPECT_TRUE(flags[i]);
+}
+
+TEST(WTF_EmbeddedFixedVector, Basic)
+{
+ std::array<unsigned, 4> array { {
+ 0, 1, 2, 3
+ } };
+ {
+ auto vector = EmbeddedFixedVector<unsigned>::create(array.begin(), array.end());
+ EXPECT_EQ(4U, vector->size());
+ EXPECT_EQ(0U, vector->at(0));
+ EXPECT_EQ(1U, vector->at(1));
+ EXPECT_EQ(2U, vector->at(2));
+ EXPECT_EQ(3U, vector->at(3));
+ }
+}
+
+TEST(WTF_EmbeddedFixedVector, Clone)
+{
+ std::array<unsigned, 4> array { {
+ 0, 1, 2, 3
+ } };
+ {
+ auto vector = EmbeddedFixedVector<unsigned>::create(array.begin(), array.end());
+ EXPECT_EQ(4U, vector->size());
+ EXPECT_EQ(0U, vector->at(0));
+ EXPECT_EQ(1U, vector->at(1));
+ EXPECT_EQ(2U, vector->at(2));
+ EXPECT_EQ(3U, vector->at(3));
+
+ auto cloned = vector->clone();
+ EXPECT_EQ(4U, cloned->size());
+ EXPECT_EQ(0U, cloned->at(0));
+ EXPECT_EQ(1U, cloned->at(1));
+ EXPECT_EQ(2U, cloned->at(2));
+ EXPECT_EQ(3U, cloned->at(3));
+ }
+}
+
+TEST(WTF_EmbeddedFixedVector, Equal)
+{
+ auto vec1 = EmbeddedFixedVector<unsigned>::create(10);
+ auto vec2 = EmbeddedFixedVector<unsigned>::create(10);
+ for (unsigned i = 0; i < 10; ++i) {
+ vec1.get()[i] = i;
+ vec2.get()[i] = i;
+ }
+ EXPECT_EQ(vec1.get(), vec2.get());
+ vec1.get()[0] = 42;
+ EXPECT_NE(vec1.get(), vec2.get());
+}
+
+}
Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/FixedVector.cpp (287219 => 287220)
--- trunk/Tools/TestWebKitAPI/Tests/WTF/FixedVector.cpp 2021-12-18 05:45:31 UTC (rev 287219)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/FixedVector.cpp 2021-12-18 10:17:05 UTC (rev 287220)
@@ -86,15 +86,15 @@
vec1[2] = 2;
FixedVector<unsigned> vec2(vec1);
- EXPECT_EQ(vec1.size(), 3U);
- EXPECT_EQ(vec2.size(), 3U);
+ EXPECT_EQ(3U, vec1.size());
+ EXPECT_EQ(3U, vec2.size());
for (unsigned i = 0; i < vec1.size(); ++i) {
- EXPECT_EQ(vec1[i], i);
- EXPECT_EQ(vec2[i], i);
+ EXPECT_EQ(i, vec1[i]);
+ EXPECT_EQ(i, vec2[i]);
}
vec1[2] = 42;
- EXPECT_EQ(vec1[2], 42U);
- EXPECT_EQ(vec2[2], 2U);
+ EXPECT_EQ(42U, vec1[2]);
+ EXPECT_EQ(2U, vec2[2]);
}
TEST(WTF_FixedVector, CopyAssign)
@@ -106,15 +106,15 @@
FixedVector<unsigned> vec2;
vec2 = vec1;
- EXPECT_EQ(vec1.size(), 3U);
- EXPECT_EQ(vec2.size(), 3U);
+ EXPECT_EQ(3U, vec1.size());
+ EXPECT_EQ(3U, vec2.size());
for (unsigned i = 0; i < vec1.size(); ++i) {
- EXPECT_EQ(vec1[i], i);
- EXPECT_EQ(vec2[i], i);
+ EXPECT_EQ(i, vec1[i]);
+ EXPECT_EQ(i, vec2[i]);
}
vec1[2] = 42;
- EXPECT_EQ(vec1[2], 42U);
- EXPECT_EQ(vec2[2], 2U);
+ EXPECT_EQ(42U, vec1[2]);
+ EXPECT_EQ(2U, vec2[2]);
}
TEST(WTF_FixedVector, Move)
@@ -125,10 +125,10 @@
vec1[2] = 2;
FixedVector<unsigned> vec2(WTFMove(vec1));
- EXPECT_EQ(vec1.size(), 0U);
- EXPECT_EQ(vec2.size(), 3U);
+ EXPECT_EQ(0U, vec1.size());
+ EXPECT_EQ(3U, vec2.size());
for (unsigned i = 0; i < vec2.size(); ++i)
- EXPECT_EQ(vec2[i], i);
+ EXPECT_EQ(i, vec2[i]);
}
TEST(WTF_FixedVector, MoveAssign)
@@ -140,21 +140,21 @@
FixedVector<unsigned> vec2;
vec2 = WTFMove(vec1);
- EXPECT_EQ(vec1.size(), 0U);
- EXPECT_EQ(vec2.size(), 3U);
+ EXPECT_EQ(0U, vec1.size());
+ EXPECT_EQ(3U, vec2.size());
for (unsigned i = 0; i < vec2.size(); ++i)
- EXPECT_EQ(vec2[i], i);
+ EXPECT_EQ(i, vec2[i]);
}
TEST(WTF_FixedVector, MoveVector)
{
auto vec1 = Vector<MoveOnly>::from(MoveOnly(0), MoveOnly(1), MoveOnly(2), MoveOnly(3));
- EXPECT_EQ(vec1.size(), 4U);
+ EXPECT_EQ(4U, vec1.size());
FixedVector<MoveOnly> vec2(WTFMove(vec1));
- EXPECT_EQ(vec1.size(), 0U);
- EXPECT_EQ(vec2.size(), 4U);
+ EXPECT_EQ(0U, vec1.size());
+ EXPECT_EQ(4U, vec2.size());
for (unsigned index = 0; index < vec2.size(); ++index)
- EXPECT_EQ(vec2[index].value(), index);
+ EXPECT_EQ(index, vec2[index].value());
}
TEST(WTF_FixedVector, MoveAssignVector)
@@ -162,13 +162,13 @@
FixedVector<MoveOnly> vec2;
{
auto vec1 = Vector<MoveOnly>::from(MoveOnly(0), MoveOnly(1), MoveOnly(2), MoveOnly(3));
- EXPECT_EQ(vec1.size(), 4U);
+ EXPECT_EQ(4U, vec1.size());
vec2 = WTFMove(vec1);
- EXPECT_EQ(vec1.size(), 0U);
+ EXPECT_EQ(0U, vec1.size());
}
- EXPECT_EQ(vec2.size(), 4U);
+ EXPECT_EQ(4U, vec2.size());
for (unsigned index = 0; index < vec2.size(); ++index)
- EXPECT_EQ(vec2[index].value(), index);
+ EXPECT_EQ(index, vec2[index].value());
}
TEST(WTF_FixedVector, Swap)
@@ -180,10 +180,10 @@
FixedVector<unsigned> vec2;
vec2.swap(vec1);
- EXPECT_EQ(vec1.size(), 0U);
- EXPECT_EQ(vec2.size(), 3U);
+ EXPECT_EQ(0U, vec1.size());
+ EXPECT_EQ(3U, vec2.size());
for (unsigned i = 0; i < vec2.size(); ++i)
- EXPECT_EQ(vec2[i], i);
+ EXPECT_EQ(i, vec2[i]);
}
TEST(WTF_FixedVector, IteratorFor)
@@ -195,7 +195,7 @@
unsigned index = 0;
for (auto iter = vec1.begin(); iter != vec1.end(); ++iter) {
- EXPECT_EQ(*iter, index);
+ EXPECT_EQ(index, *iter);
++index;
}
}
@@ -210,7 +210,7 @@
unsigned index = 0;
for (auto iter = vec1.rbegin(); iter != vec1.rend(); ++iter) {
++index;
- EXPECT_EQ(*iter, 3U - index);
+ EXPECT_EQ(3U - index, *iter);
}
}
@@ -220,7 +220,7 @@
vec1.fill(42);
for (auto& value : vec1)
- EXPECT_EQ(value, 42U);
+ EXPECT_EQ(42U, value);
}
struct DestructorObserver {
@@ -293,7 +293,7 @@
FixedVector<unsigned> vec1(3);
auto* data1 = vec1.data();
FixedVector<unsigned> vec2(WTFMove(vec1));
- EXPECT_EQ(vec2.data(), data1);
+ EXPECT_EQ(data1, vec2.data());
}
{
FixedVector<unsigned> vec1(3);
@@ -300,7 +300,7 @@
auto* data1 = vec1.data();
FixedVector<unsigned> vec2;
vec2 = WTFMove(vec1);
- EXPECT_EQ(vec2.data(), data1);
+ EXPECT_EQ(data1, vec2.data());
}
}
@@ -311,8 +311,8 @@
vec1.append(FixedVector<unsigned>(3));
auto* data1 = vec1[0].data();
FixedVector<FixedVector<unsigned>> vec2(WTFMove(vec1));
- EXPECT_EQ(vec2.size(), 1U);
- EXPECT_EQ(vec2[0].data(), data1);
+ EXPECT_EQ(1U, vec2.size());
+ EXPECT_EQ(data1, vec2[0].data());
}
{
Vector<FixedVector<unsigned>> vec1;
@@ -320,9 +320,39 @@
auto* data1 = vec1[0].data();
FixedVector<FixedVector<unsigned>> vec2;
vec2 = WTFMove(vec1);
- EXPECT_EQ(vec2.size(), 1U);
- EXPECT_EQ(vec2[0].data(), data1);
+ EXPECT_EQ(1U, vec2.size());
+ EXPECT_EQ(data1, vec2[0].data());
}
}
+TEST(WTF_FixedVector, Offset)
+{
+ EXPECT_EQ(0, FixedVector<unsigned>::offsetOfStorage());
+ EXPECT_EQ(4, FixedVector<unsigned>::Storage::offsetOfData());
+ EXPECT_EQ(0, FixedVector<void*>::offsetOfStorage());
+ EXPECT_EQ(sizeof(void*), static_cast<unsigned>(FixedVector<void*>::Storage::offsetOfData()));
+}
+
+TEST(WTF_FixedVector, Equal)
+{
+ {
+ FixedVector<unsigned> vec1(10);
+ FixedVector<unsigned> vec2(10);
+ for (unsigned i = 0; i < 10; ++i) {
+ vec1[i] = i;
+ vec2[i] = i;
+ }
+ EXPECT_EQ(vec2, vec1);
+ vec1[0] = 42;
+ EXPECT_NE(vec1, vec2);
+ }
+ {
+ FixedVector<unsigned> vec1;
+ FixedVector<unsigned> vec2;
+ FixedVector<unsigned> vec3(0);
+ EXPECT_EQ(vec2, vec1);
+ EXPECT_EQ(vec3, vec1);
+ }
+}
+
} // namespace TestWebKitAPI
Added: trunk/Tools/TestWebKitAPI/Tests/WTF/RefCountedFixedVector.cpp (0 => 287220)
--- trunk/Tools/TestWebKitAPI/Tests/WTF/RefCountedFixedVector.cpp (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/RefCountedFixedVector.cpp 2021-12-18 10:17:05 UTC (rev 287220)
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+
+#include "MoveOnly.h"
+#include <wtf/RefCountedFixedVector.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF_RefCountedFixedVector, Empty)
+{
+ auto vector = RefCountedFixedVector<unsigned>::create(0);
+ EXPECT_TRUE(vector->isEmpty());
+ EXPECT_EQ(0U, vector->size());
+}
+
+TEST(WTF_RefCountedFixedVector, Iterator)
+{
+ auto intVector = RefCountedFixedVector<unsigned>::create(4);
+ intVector.get()[0] = 10;
+ intVector.get()[1] = 11;
+ intVector.get()[2] = 12;
+ intVector.get()[3] = 13;
+
+ auto it = intVector->begin();
+ auto end = intVector->end();
+ EXPECT_TRUE(end != it);
+
+ EXPECT_EQ(10U, *it);
+ ++it;
+ EXPECT_EQ(11U, *it);
+ ++it;
+ EXPECT_EQ(12U, *it);
+ ++it;
+ EXPECT_EQ(13U, *it);
+ ++it;
+
+ EXPECT_TRUE(end == it);
+}
+
+TEST(WTF_RefCountedFixedVector, OverloadedOperatorAmpersand)
+{
+ struct Test {
+ private:
+ Test* operator&() = delete;
+ };
+
+ auto vector = RefCountedFixedVector<Test>::create(1);
+ vector.get()[0] = Test();
+}
+
+TEST(WTF_RefCountedFixedVector, Copy)
+{
+ auto vec1 = RefCountedFixedVector<unsigned>::create(3);
+ vec1.get()[0] = 0;
+ vec1.get()[1] = 1;
+ vec1.get()[2] = 2;
+
+ auto vec2 = RefCountedFixedVector<unsigned>::create(vec1->begin(), vec1->end());
+ EXPECT_EQ(3U, vec1->size());
+ EXPECT_EQ(3U, vec2->size());
+ for (unsigned i = 0; i < vec1->size(); ++i) {
+ EXPECT_EQ(i, vec1.get()[i]);
+ EXPECT_EQ(i, vec2.get()[i]);
+ }
+ vec1.get()[2] = 42;
+ EXPECT_EQ(42U, vec1.get()[2]);
+ EXPECT_EQ(2U, vec2.get()[2]);
+}
+
+TEST(WTF_RefCountedFixedVector, CopyVector)
+{
+ auto vec1 = Vector<unsigned>::from(0, 1, 2, 3);
+ EXPECT_EQ(4U, vec1.size());
+ auto vec2 = RefCountedFixedVector<unsigned>::createFromVector(vec1);
+ EXPECT_EQ(4U, vec1.size());
+ EXPECT_EQ(4U, vec2->size());
+ for (unsigned i = 0; i < vec1.size(); ++i) {
+ EXPECT_EQ(i, vec1[i]);
+ EXPECT_EQ(i, vec2.get()[i]);
+ }
+ vec1[2] = 42;
+ EXPECT_EQ(42U, vec1[2]);
+ EXPECT_EQ(2U, vec2.get()[2]);
+}
+
+TEST(WTF_RefCountedFixedVector, MoveVector)
+{
+ auto vec1 = Vector<MoveOnly>::from(MoveOnly(0), MoveOnly(1), MoveOnly(2), MoveOnly(3));
+ EXPECT_EQ(4U, vec1.size());
+ auto vec2 = RefCountedFixedVector<MoveOnly>::createFromVector(WTFMove(vec1));
+ EXPECT_EQ(0U, vec1.size());
+ EXPECT_EQ(4U, vec2->size());
+ for (unsigned index = 0; index < vec2->size(); ++index)
+ EXPECT_EQ(index, vec2.get()[index].value());
+}
+
+TEST(WTF_RefCountedFixedVector, IteratorFor)
+{
+ auto vec1 = RefCountedFixedVector<unsigned>::create(3);
+ vec1.get()[0] = 0;
+ vec1.get()[1] = 1;
+ vec1.get()[2] = 2;
+
+ unsigned index = 0;
+ for (auto iter = vec1->begin(); iter != vec1->end(); ++iter) {
+ EXPECT_EQ(index, *iter);
+ ++index;
+ }
+}
+
+TEST(WTF_RefCountedFixedVector, Reverse)
+{
+ auto vec1 = RefCountedFixedVector<unsigned>::create(3);
+ vec1.get()[0] = 0;
+ vec1.get()[1] = 1;
+ vec1.get()[2] = 2;
+
+ unsigned index = 0;
+ for (auto iter = vec1->rbegin(); iter != vec1->rend(); ++iter) {
+ ++index;
+ EXPECT_EQ(3U - index, *iter);
+ }
+}
+
+TEST(WTF_RefCountedFixedVector, Fill)
+{
+ auto vec1 = RefCountedFixedVector<unsigned>::create(3);
+ vec1->fill(42);
+
+ for (auto& value : vec1.get())
+ EXPECT_EQ(value, 42U);
+}
+
+struct DestructorObserver {
+ DestructorObserver() = default;
+
+ DestructorObserver(bool* destructed)
+ : destructed(destructed)
+ {
+ }
+
+ ~DestructorObserver()
+ {
+ if (destructed)
+ *destructed = true;
+ }
+
+ DestructorObserver(DestructorObserver&& other)
+ : destructed(other.destructed)
+ {
+ other.destructed = nullptr;
+ }
+
+ DestructorObserver& operator=(DestructorObserver&& other)
+ {
+ destructed = other.destructed;
+ other.destructed = nullptr;
+ return *this;
+ }
+
+ bool* destructed { nullptr };
+};
+
+TEST(WTF_RefCountedFixedVector, Destructor)
+{
+ Vector<bool> flags(3, false);
+ {
+ auto vector = RefCountedFixedVector<DestructorObserver>::create(flags.size());
+ for (unsigned i = 0; i < flags.size(); ++i)
+ vector.get()[i] = DestructorObserver(&flags[i]);
+ for (unsigned i = 0; i < flags.size(); ++i)
+ EXPECT_FALSE(flags[i]);
+ }
+ for (unsigned i = 0; i < flags.size(); ++i)
+ EXPECT_TRUE(flags[i]);
+}
+
+TEST(WTF_RefCountedFixedVector, DestructorAfterMove)
+{
+ Vector<bool> flags(3, false);
+ {
+ RefPtr<RefCountedFixedVector<DestructorObserver>> outerVector;
+ {
+ RefPtr<RefCountedFixedVector<DestructorObserver>> outerVector2;
+ {
+ auto vector = RefCountedFixedVector<DestructorObserver>::create(flags.size());
+ for (unsigned i = 0; i < flags.size(); ++i)
+ vector.get()[i] = DestructorObserver(&flags[i]);
+ for (unsigned i = 0; i < flags.size(); ++i)
+ EXPECT_FALSE(flags[i]);
+ outerVector = vector.copyRef();
+ outerVector2 = vector.copyRef();
+ }
+ for (unsigned i = 0; i < flags.size(); ++i)
+ EXPECT_FALSE(flags[i]);
+ EXPECT_EQ(outerVector.get(), outerVector2.get());
+ }
+ for (unsigned i = 0; i < flags.size(); ++i)
+ EXPECT_FALSE(flags[i]);
+ }
+ for (unsigned i = 0; i < flags.size(); ++i)
+ EXPECT_TRUE(flags[i]);
+}
+
+TEST(WTF_RefCountedFixedVector, Basic)
+{
+ std::array<unsigned, 4> array { {
+ 0, 1, 2, 3
+ } };
+ {
+ auto vector = RefCountedFixedVector<unsigned>::create(array.begin(), array.end());
+ EXPECT_EQ(4U, vector->size());
+ EXPECT_EQ(0U, vector->at(0));
+ EXPECT_EQ(1U, vector->at(1));
+ EXPECT_EQ(2U, vector->at(2));
+ EXPECT_EQ(3U, vector->at(3));
+ }
+}
+
+TEST(WTF_RefCountedFixedVector, Clone)
+{
+ std::array<unsigned, 4> array { {
+ 0, 1, 2, 3
+ } };
+ {
+ auto vector = RefCountedFixedVector<unsigned>::create(array.begin(), array.end());
+ EXPECT_EQ(4U, vector->size());
+ EXPECT_EQ(0U, vector->at(0));
+ EXPECT_EQ(1U, vector->at(1));
+ EXPECT_EQ(2U, vector->at(2));
+ EXPECT_EQ(3U, vector->at(3));
+
+ auto cloned = vector->clone();
+ EXPECT_EQ(4U, cloned->size());
+ EXPECT_EQ(0U, cloned->at(0));
+ EXPECT_EQ(1U, cloned->at(1));
+ EXPECT_EQ(2U, cloned->at(2));
+ EXPECT_EQ(3U, cloned->at(3));
+ }
+}
+
+TEST(WTF_RefCountedFixedVector, Equal)
+{
+ auto vec1 = RefCountedFixedVector<unsigned>::create(10);
+ auto vec2 = RefCountedFixedVector<unsigned>::create(10);
+ for (unsigned i = 0; i < 10; ++i) {
+ vec1.get()[i] = i;
+ vec2.get()[i] = i;
+ }
+ EXPECT_EQ(vec1.get(), vec2.get());
+ vec1.get()[0] = 42;
+ EXPECT_NE(vec1.get(), vec2.get());
+}
+
+}