[K/N] Remove usage of legacy allocation stuff ^KT-52130

Merge-request: KT-MR-6182
Merged-by: Alexander Shabalin <Alexander.Shabalin@jetbrains.com>
This commit is contained in:
Alexander Shabalin
2022-04-29 10:12:44 +00:00
committed by Space
parent cb35e868cc
commit 4a66cd0c69
73 changed files with 590 additions and 593 deletions
@@ -96,7 +96,7 @@ gc::ConcurrentMarkAndSweep::ConcurrentMarkAndSweep(
mm::ObjectFactory<ConcurrentMarkAndSweep>& objectFactory, GCScheduler& gcScheduler) noexcept :
objectFactory_(objectFactory),
gcScheduler_(gcScheduler),
finalizerProcessor_(make_unique<FinalizerProcessor>([this](int64_t epoch) { state_.finalized(epoch); })) {
finalizerProcessor_(std_support::make_unique<FinalizerProcessor>([this](int64_t epoch) { state_.finalized(epoch); })) {
gcScheduler_.SetScheduleGC([this]() NO_INLINE {
RuntimeLogDebug({kTagGC}, "Scheduling GC by thread %d", konan::currentThreadId());
// This call acquires a lock, so we need to ensure that we're in the safe state.
@@ -15,6 +15,7 @@
#include "Types.h"
#include "Utils.hpp"
#include "GCState.hpp"
#include "std_support/Memory.hpp"
namespace kotlin {
@@ -105,7 +106,7 @@ private:
uint64_t lastGCTimestampUs_ = 0;
GCStateHolder state_;
ScopedThread gcThread_;
KStdUniquePtr<FinalizerProcessor> finalizerProcessor_;
std_support::unique_ptr<FinalizerProcessor> finalizerProcessor_;
MarkQueue markQueue_;
};
@@ -22,6 +22,7 @@
#include "SingleThreadExecutor.hpp"
#include "TestSupport.hpp"
#include "ThreadData.hpp"
#include "std_support/Vector.hpp"
using namespace kotlin;
@@ -187,8 +188,8 @@ test_support::Object<Payload>& AllocateObjectWithFinalizer(mm::ThreadData& threa
return test_support::Object<Payload>::FromObjHeader(holder.obj());
}
KStdVector<ObjHeader*> Alive(mm::ThreadData& threadData) {
KStdVector<ObjHeader*> objects;
std_support::vector<ObjHeader*> Alive(mm::ThreadData& threadData) {
std_support::vector<ObjHeader*> objects;
for (auto node : threadData.gc().impl().objectFactoryThreadQueue()) {
objects.push_back(node.GetObjHeader());
}
@@ -657,7 +658,7 @@ public:
StackObjectHolder& AddStackRoot() {
RuntimeAssert(std::this_thread::get_id() == executor_.threadId(), "AddStackRoot can only be called in the mutator thread");
auto& context = executor_.context();
auto holder = make_unique<StackObjectHolder>(*context.memory_->memoryState()->GetThreadData());
auto holder = std_support::make_unique<StackObjectHolder>(*context.memory_->memoryState()->GetThreadData());
auto& holderRef = *holder;
context.stackRoots_.push_back(std::move(holder));
return holderRef;
@@ -666,7 +667,7 @@ public:
StackObjectHolder& AddStackRoot(ObjHeader* object) {
RuntimeAssert(std::this_thread::get_id() == executor_.threadId(), "AddStackRoot can only be called in the mutator thread");
auto& context = executor_.context();
auto holder = make_unique<StackObjectHolder>(object);
auto holder = std_support::make_unique<StackObjectHolder>(object);
auto& holderRef = *holder;
context.stackRoots_.push_back(std::move(holder));
return holderRef;
@@ -675,7 +676,7 @@ public:
GlobalObjectHolder& AddGlobalRoot() {
RuntimeAssert(std::this_thread::get_id() == executor_.threadId(), "AddGlobalRoot can only be called in the mutator thread");
auto& context = executor_.context();
auto holder = make_unique<GlobalObjectHolder>(*context.memory_->memoryState()->GetThreadData());
auto holder = std_support::make_unique<GlobalObjectHolder>(*context.memory_->memoryState()->GetThreadData());
auto& holderRef = *holder;
context.globalRoots_.push_back(std::move(holder));
return holderRef;
@@ -684,21 +685,21 @@ public:
GlobalObjectHolder& AddGlobalRoot(ObjHeader* object) {
RuntimeAssert(std::this_thread::get_id() == executor_.threadId(), "AddGlobalRoot can only be called in the mutator thread");
auto& context = executor_.context();
auto holder = make_unique<GlobalObjectHolder>(*context.memory_->memoryState()->GetThreadData(), object);
auto holder = std_support::make_unique<GlobalObjectHolder>(*context.memory_->memoryState()->GetThreadData(), object);
auto& holderRef = *holder;
context.globalRoots_.push_back(std::move(holder));
return holderRef;
}
KStdVector<ObjHeader*> Alive() { return ::Alive(*executor_.context().memory_->memoryState()->GetThreadData()); }
std_support::vector<ObjHeader*> Alive() { return ::Alive(*executor_.context().memory_->memoryState()->GetThreadData()); }
private:
struct Context {
KStdUniquePtr<ScopedMemoryInit> memory_;
KStdVector<KStdUniquePtr<StackObjectHolder>> stackRoots_;
KStdVector<KStdUniquePtr<GlobalObjectHolder>> globalRoots_;
std_support::unique_ptr<ScopedMemoryInit> memory_;
std_support::vector<std_support::unique_ptr<StackObjectHolder>> stackRoots_;
std_support::vector<std_support::unique_ptr<GlobalObjectHolder>> globalRoots_;
Context() : memory_(make_unique<ScopedMemoryInit>()) {
Context() : memory_(std_support::make_unique<ScopedMemoryInit>()) {
// SingleThreadExecutor must work in the runnable state, so that GC does not collect between tasks.
AssertThreadState(memory_->memoryState(), ThreadState::kRunnable);
}
@@ -710,10 +711,10 @@ private:
} // namespace
TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsCollect) {
KStdVector<Mutator> mutators(kDefaultThreadCount);
KStdVector<ObjHeader*> globals(kDefaultThreadCount);
KStdVector<ObjHeader*> locals(kDefaultThreadCount);
KStdVector<ObjHeader*> reachables(kDefaultThreadCount);
std_support::vector<Mutator> mutators(kDefaultThreadCount);
std_support::vector<ObjHeader*> globals(kDefaultThreadCount);
std_support::vector<ObjHeader*> locals(kDefaultThreadCount);
std_support::vector<ObjHeader*> reachables(kDefaultThreadCount);
auto expandRootSet = [&globals, &locals, &reachables](mm::ThreadData& threadData, Mutator& mutator, int i) {
auto& global = mutator.AddGlobalRoot();
@@ -732,7 +733,7 @@ TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsCollect) {
.wait();
}
KStdVector<std::future<void>> gcFutures(kDefaultThreadCount);
std_support::vector<std::future<void>> gcFutures(kDefaultThreadCount);
gcFutures[0] = mutators[0].Execute([](mm::ThreadData& threadData, Mutator& mutator) { threadData.gc().ScheduleAndWaitFullGC(); });
@@ -749,7 +750,7 @@ TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsCollect) {
future.wait();
}
KStdVector<ObjHeader*> expectedAlive;
std_support::vector<ObjHeader*> expectedAlive;
for (auto& global : globals) {
expectedAlive.push_back(global);
}
@@ -766,10 +767,10 @@ TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsCollect) {
}
TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsAllCollect) {
KStdVector<Mutator> mutators(kDefaultThreadCount);
KStdVector<ObjHeader*> globals(kDefaultThreadCount);
KStdVector<ObjHeader*> locals(kDefaultThreadCount);
KStdVector<ObjHeader*> reachables(kDefaultThreadCount);
std_support::vector<Mutator> mutators(kDefaultThreadCount);
std_support::vector<ObjHeader*> globals(kDefaultThreadCount);
std_support::vector<ObjHeader*> locals(kDefaultThreadCount);
std_support::vector<ObjHeader*> reachables(kDefaultThreadCount);
auto expandRootSet = [&globals, &locals, &reachables](mm::ThreadData& threadData, Mutator& mutator, int i) {
auto& global = mutator.AddGlobalRoot();
@@ -788,7 +789,7 @@ TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsAllCollect) {
.wait();
}
KStdVector<std::future<void>> gcFutures(kDefaultThreadCount);
std_support::vector<std::future<void>> gcFutures(kDefaultThreadCount);
for (int i = 0; i < kDefaultThreadCount; ++i) {
gcFutures[i] = mutators[i].Execute([](mm::ThreadData& threadData, Mutator& mutator) {
@@ -811,7 +812,7 @@ TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsAllCollect) {
.wait();
}
KStdVector<ObjHeader*> expectedAlive;
std_support::vector<ObjHeader*> expectedAlive;
for (auto& global : globals) {
expectedAlive.push_back(global);
}
@@ -828,10 +829,10 @@ TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsAllCollect) {
}
TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsAddToRootSetAfterCollectionRequested) {
KStdVector<Mutator> mutators(kDefaultThreadCount);
KStdVector<ObjHeader*> globals(kDefaultThreadCount);
KStdVector<ObjHeader*> locals(kDefaultThreadCount);
KStdVector<ObjHeader*> reachables(kDefaultThreadCount);
std_support::vector<Mutator> mutators(kDefaultThreadCount);
std_support::vector<ObjHeader*> globals(kDefaultThreadCount);
std_support::vector<ObjHeader*> locals(kDefaultThreadCount);
std_support::vector<ObjHeader*> reachables(kDefaultThreadCount);
auto allocateInHeap = [&globals, &locals, &reachables](mm::ThreadData& threadData, Mutator& mutator, int i) {
auto& global = AllocateObject(threadData);
@@ -865,7 +866,7 @@ TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsAddToRootSetAfterCollectionRe
.wait();
}
KStdVector<std::future<void>> gcFutures(kDefaultThreadCount);
std_support::vector<std::future<void>> gcFutures(kDefaultThreadCount);
gcFutures[0] = mutators[0].Execute([](mm::ThreadData& threadData, Mutator& mutator) { threadData.gc().ScheduleAndWaitFullGC(); });
// Spin until thread suspension is requested.
@@ -883,7 +884,7 @@ TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsAddToRootSetAfterCollectionRe
future.wait();
}
KStdVector<ObjHeader*> expectedAlive;
std_support::vector<ObjHeader*> expectedAlive;
for (auto& global : globals) {
expectedAlive.push_back(global);
}
@@ -900,10 +901,10 @@ TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsAddToRootSetAfterCollectionRe
}
TEST_F(ConcurrentMarkAndSweepTest, CrossThreadReference) {
KStdVector<Mutator> mutators(kDefaultThreadCount);
KStdVector<ObjHeader*> globals(kDefaultThreadCount);
KStdVector<ObjHeader*> locals(kDefaultThreadCount);
KStdVector<ObjHeader*> reachables(2 * kDefaultThreadCount);
std_support::vector<Mutator> mutators(kDefaultThreadCount);
std_support::vector<ObjHeader*> globals(kDefaultThreadCount);
std_support::vector<ObjHeader*> locals(kDefaultThreadCount);
std_support::vector<ObjHeader*> reachables(2 * kDefaultThreadCount);
auto expandRootSet = [&globals, &locals, &reachables](mm::ThreadData& threadData, Mutator& mutator, int i) {
auto& global = mutator.AddGlobalRoot();
@@ -929,7 +930,7 @@ TEST_F(ConcurrentMarkAndSweepTest, CrossThreadReference) {
.wait();
}
KStdVector<std::future<void>> gcFutures(kDefaultThreadCount);
std_support::vector<std::future<void>> gcFutures(kDefaultThreadCount);
gcFutures[0] = mutators[0].Execute([](mm::ThreadData& threadData, Mutator& mutator) { threadData.gc().ScheduleAndWaitFullGC(); });
@@ -946,7 +947,7 @@ TEST_F(ConcurrentMarkAndSweepTest, CrossThreadReference) {
future.wait();
}
KStdVector<ObjHeader*> expectedAlive;
std_support::vector<ObjHeader*> expectedAlive;
for (auto& global : globals) {
expectedAlive.push_back(global);
}
@@ -966,7 +967,7 @@ TEST_F(ConcurrentMarkAndSweepTest, CrossThreadReference) {
}
TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsWeaks) {
KStdVector<Mutator> mutators(kDefaultThreadCount);
std_support::vector<Mutator> mutators(kDefaultThreadCount);
ObjHeader* globalRoot = nullptr;
WeakCounter* weak = nullptr;
@@ -990,7 +991,7 @@ TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsWeaks) {
mutators[i].Execute([](mm::ThreadData& threadData, Mutator& mutator) {}).wait();
}
KStdVector<std::future<void>> gcFutures(kDefaultThreadCount);
std_support::vector<std::future<void>> gcFutures(kDefaultThreadCount);
gcFutures[0] = mutators[0].Execute([weak](mm::ThreadData& threadData, Mutator& mutator) {
threadData.gc().ScheduleAndWaitFullGC();
@@ -1018,11 +1019,11 @@ TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsWeaks) {
}
TEST_F(ConcurrentMarkAndSweepTest, NewThreadsWhileRequestingCollection) {
KStdVector<Mutator> mutators(kDefaultThreadCount);
KStdVector<ObjHeader*> globals(2 * kDefaultThreadCount);
KStdVector<ObjHeader*> locals(2 * kDefaultThreadCount);
KStdVector<ObjHeader*> reachables(2 * kDefaultThreadCount);
KStdVector<ObjHeader*> unreachables(2 * kDefaultThreadCount);
std_support::vector<Mutator> mutators(kDefaultThreadCount);
std_support::vector<ObjHeader*> globals(2 * kDefaultThreadCount);
std_support::vector<ObjHeader*> locals(2 * kDefaultThreadCount);
std_support::vector<ObjHeader*> reachables(2 * kDefaultThreadCount);
std_support::vector<ObjHeader*> unreachables(2 * kDefaultThreadCount);
auto expandRootSet = [&globals, &locals, &reachables, &unreachables](mm::ThreadData& threadData, Mutator& mutator, int i) {
auto& global = mutator.AddGlobalRoot();
@@ -1042,7 +1043,7 @@ TEST_F(ConcurrentMarkAndSweepTest, NewThreadsWhileRequestingCollection) {
.wait();
}
KStdVector<std::future<void>> gcFutures(kDefaultThreadCount);
std_support::vector<std::future<void>> gcFutures(kDefaultThreadCount);
gcFutures[0] = mutators[0].Execute([](mm::ThreadData& threadData, Mutator& mutator) { threadData.gc().ScheduleAndWaitFullGC(); });
@@ -1051,8 +1052,8 @@ TEST_F(ConcurrentMarkAndSweepTest, NewThreadsWhileRequestingCollection) {
}
// Now start attaching new threads.
KStdVector<Mutator> newMutators(kDefaultThreadCount);
KStdVector<std::future<void>> attachFutures(kDefaultThreadCount);
std_support::vector<Mutator> newMutators(kDefaultThreadCount);
std_support::vector<std::future<void>> attachFutures(kDefaultThreadCount);
for (int i = 0; i < kDefaultThreadCount; ++i) {
attachFutures[i] = newMutators[i].Execute([i, expandRootSet](mm::ThreadData& threadData, Mutator& mutator) { expandRootSet(threadData, mutator, i + kDefaultThreadCount); });
@@ -1076,7 +1077,7 @@ TEST_F(ConcurrentMarkAndSweepTest, NewThreadsWhileRequestingCollection) {
// Old mutators don't even see alive objects from the new threads yet (as the latter ones have not published anything).
KStdVector<ObjHeader*> expectedAlive;
std_support::vector<ObjHeader*> expectedAlive;
for (int i = 0; i < kDefaultThreadCount; ++i) {
expectedAlive.push_back(globals[i]);
expectedAlive.push_back(locals[i]);
@@ -1088,7 +1089,7 @@ TEST_F(ConcurrentMarkAndSweepTest, NewThreadsWhileRequestingCollection) {
}
for (int i = 0; i < kDefaultThreadCount; ++i) {
KStdVector<ObjHeader*> aliveForThisThread(expectedAlive.begin(), expectedAlive.end());
std_support::vector<ObjHeader*> aliveForThisThread(expectedAlive.begin(), expectedAlive.end());
aliveForThisThread.push_back(globals[kDefaultThreadCount + i]);
aliveForThisThread.push_back(locals[kDefaultThreadCount + i]);
aliveForThisThread.push_back(reachables[kDefaultThreadCount + i]);
@@ -1100,7 +1101,7 @@ TEST_F(ConcurrentMarkAndSweepTest, NewThreadsWhileRequestingCollection) {
TEST_F(ConcurrentMarkAndSweepTest, FreeObjectWithFreeWeakReversedOrder) {
KStdVector<Mutator> mutators(2);
std_support::vector<Mutator> mutators(2);
std::atomic<test_support::Object<Payload>*> object1 = nullptr;
std::atomic<WeakCounter*> weak = nullptr;
std::atomic<bool> done = false;
@@ -7,6 +7,7 @@
#include "GC.hpp"
#include "ThreadSuspension.hpp"
#include "std_support/Memory.hpp"
using namespace kotlin;
@@ -19,7 +20,7 @@ ALWAYS_INLINE void SafePointRegular(gc::GC::ThreadData& threadData, size_t weigh
} // namespace
gc::GC::ThreadData::ThreadData(GC& gc, mm::ThreadData& threadData) noexcept : impl_(make_unique<Impl>(gc, threadData)) {}
gc::GC::ThreadData::ThreadData(GC& gc, mm::ThreadData& threadData) noexcept : impl_(std_support::make_unique<Impl>(gc, threadData)) {}
gc::GC::ThreadData::~ThreadData() = default;
@@ -59,7 +60,7 @@ void gc::GC::ThreadData::OnStoppedForGC() noexcept {
impl_->gcScheduler().OnStoppedForGC();
}
gc::GC::GC() noexcept : impl_(make_unique<Impl>()) {}
gc::GC::GC() noexcept : impl_(std_support::make_unique<Impl>()) {}
gc::GC::~GC() = default;
@@ -5,15 +5,17 @@
#pragma once
#include "Alloc.h"
#include <utility>
#include "std_support/CStdlib.hpp"
namespace kotlin {
namespace gc {
class AlignedAllocator {
public:
void* Alloc(size_t size, size_t alignment) noexcept { return konanAllocAlignedMemory(size, alignment); }
static void Free(void* instance) noexcept { konanFreeMemory(instance); }
void* Alloc(size_t size, size_t alignment) noexcept { return std_support::aligned_calloc(alignment, 1, size); }
static void Free(void* instance) noexcept { std_support::free(instance); }
};
template <typename BaseAllocator, typename GCThreadData>
@@ -8,7 +8,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "Types.h"
#include "std_support/Memory.hpp"
using namespace kotlin;
@@ -28,7 +28,7 @@ public:
void* Alloc(size_t size, size_t alignment) { return mock_->Alloc(size, alignment); }
private:
KStdUniquePtr<testing::StrictMock<MockAllocator>> mock_ = make_unique<testing::StrictMock<MockAllocator>>();
std_support::unique_ptr<testing::StrictMock<MockAllocator>> mock_ = std_support::make_unique<testing::StrictMock<MockAllocator>>();
};
class MockGC {
@@ -9,6 +9,7 @@
#include "Memory.h"
#include "Types.h"
#include "Utils.hpp"
#include "std_support/Memory.hpp"
namespace kotlin {
@@ -46,7 +47,7 @@ public:
void OnStoppedForGC() noexcept;
private:
KStdUniquePtr<Impl> impl_;
std_support::unique_ptr<Impl> impl_;
};
GC() noexcept;
@@ -65,7 +66,7 @@ public:
bool FinalizersThreadIsRunning() noexcept;
private:
KStdUniquePtr<Impl> impl_;
std_support::unique_ptr<Impl> impl_;
};
inline constexpr bool kSupportsMultipleMutators = true;
@@ -19,25 +19,25 @@ using namespace kotlin;
namespace {
KStdUniquePtr<gc::GCSchedulerData> MakeGCSchedulerData(
std_support::unique_ptr<gc::GCSchedulerData> MakeGCSchedulerData(
gc::SchedulerType type, gc::GCSchedulerConfig& config, std::function<void()> scheduleGC) noexcept {
switch (type) {
case gc::SchedulerType::kDisabled:
RuntimeLogDebug({kTagGC}, "GC scheduler disabled");
return ::make_unique<gc::internal::GCEmptySchedulerData>();
return std_support::make_unique<gc::internal::GCEmptySchedulerData>();
case gc::SchedulerType::kWithTimer:
#ifndef KONAN_NO_THREADS
RuntimeLogDebug({kTagGC}, "Initializing timer-based GC scheduler");
return ::make_unique<gc::internal::GCSchedulerDataWithTimer<steady_clock>>(config, std::move(scheduleGC));
return std_support::make_unique<gc::internal::GCSchedulerDataWithTimer<steady_clock>>(config, std::move(scheduleGC));
#else
RuntimeFail("GC scheduler with timer is not supported on this platform");
#endif
case gc::SchedulerType::kOnSafepoints:
RuntimeLogDebug({kTagGC}, "Initializing safe-point-based GC scheduler");
return ::make_unique<gc::internal::GCSchedulerDataOnSafepoints<steady_clock>>(config, std::move(scheduleGC));
return std_support::make_unique<gc::internal::GCSchedulerDataOnSafepoints<steady_clock>>(config, std::move(scheduleGC));
case gc::SchedulerType::kAggressive:
RuntimeLogDebug({kTagGC}, "Initializing aggressive GC scheduler");
return ::make_unique<gc::internal::GCSchedulerDataAggressive>(config, std::move(scheduleGC));
return std_support::make_unique<gc::internal::GCSchedulerDataAggressive>(config, std::move(scheduleGC));
}
}
@@ -17,6 +17,7 @@
#include "Logging.hpp"
#include "Types.h"
#include "Utils.hpp"
#include "std_support/Memory.hpp"
namespace kotlin {
namespace gc {
@@ -159,7 +160,7 @@ public:
private:
GCSchedulerConfig config_;
KStdUniquePtr<GCSchedulerData> gcData_;
std_support::unique_ptr<GCSchedulerData> gcData_;
std::function<void()> scheduleGC_;
};
@@ -15,6 +15,7 @@
#include "GCSchedulerImpl.hpp"
#include "SingleThreadExecutor.hpp"
#include "TestSupport.hpp"
#include "std_support/Vector.hpp"
using namespace kotlin;
@@ -315,7 +316,7 @@ public:
explicit GCSchedulerDataTestApi(GCSchedulerConfig& config) : scheduler_(config, scheduleGC_.AsStdFunction()) {
mutators_.reserve(MutatorCount);
for (int i = 0; i < MutatorCount; ++i) {
mutators_.emplace_back(make_unique<MutatorThread>(
mutators_.emplace_back(std_support::make_unique<MutatorThread>(
config, [this](GCSchedulerThreadData& threadData) { scheduler_.UpdateFromThreadData(threadData); }));
}
}
@@ -334,7 +335,7 @@ public:
}
private:
KStdVector<KStdUniquePtr<MutatorThread>> mutators_;
std_support::vector<std_support::unique_ptr<MutatorThread>> mutators_;
testing::MockFunction<void()> scheduleGC_;
GCScheduler scheduler_;
};
@@ -367,7 +368,7 @@ TEST_F(GCSchedulerDataOnSafePointsTest, CollectOnTargetHeapReached) {
GCSchedulerDataOnSafepointsTestApi<mutatorsCount> schedulerTestApi(config);
EXPECT_CALL(schedulerTestApi.scheduleGC(), Call()).Times(0);
KStdVector<std::future<void>> futures;
std_support::vector<std::future<void>> futures;
for (int i = 0; i < mutatorsCount; ++i) {
futures.push_back(schedulerTestApi.Allocate(i, 10));
}
@@ -405,7 +406,7 @@ TEST_F(GCSchedulerDataOnSafePointsTest, CollectOnTimeoutReached) {
EXPECT_CALL(schedulerTestApi.scheduleGC(), Call()).Times(0);
schedulerTestApi.advance_time(microseconds(5));
KStdVector<std::future<void>> futures;
std_support::vector<std::future<void>> futures;
for (int i = 0; i < mutatorsCount; ++i) {
futures.push_back(schedulerTestApi.Allocate(i, 0));
}
@@ -550,7 +551,7 @@ TEST_F(GCSchedulerDataWithTimerTest, CollectOnTargetHeapReached) {
GCSchedulerDataWithTimerTestApi<mutatorsCount> schedulerTestApi(config);
EXPECT_CALL(schedulerTestApi.scheduleGC(), Call()).Times(0);
KStdVector<std::future<void>> futures;
std_support::vector<std::future<void>> futures;
for (int i = 0; i < mutatorsCount; ++i) {
futures.push_back(schedulerTestApi.Allocate(i, 10));
}
@@ -14,6 +14,8 @@
#include "FinalizerHooks.hpp"
#include "ObjectTestSupport.hpp"
#include "Utils.hpp"
#include "std_support/UnorderedSet.hpp"
#include "std_support/Vector.hpp"
using namespace kotlin;
@@ -108,7 +110,7 @@ public:
class ScopedMarkTraits : private Pinned {
public:
using MarkQueue = KStdVector<ObjHeader*>;
using MarkQueue = std_support::vector<ObjHeader*>;
ScopedMarkTraits() {
RuntimeAssert(instance_ == nullptr, "Only one ScopedMarkTraits is allowed");
@@ -120,7 +122,7 @@ public:
instance_ = nullptr;
}
const KStdUnorderedSet<ObjHeader*>& marked() const { return marked_; }
const std_support::unordered_set<ObjHeader*>& marked() const { return marked_; }
static bool isEmpty(const MarkQueue& queue) noexcept {
return queue.empty();
@@ -146,7 +148,7 @@ public:
private:
static ScopedMarkTraits* instance_;
KStdUnorderedSet<ObjHeader*> marked_;
std_support::unordered_set<ObjHeader*> marked_;
};
// static
@@ -154,10 +156,10 @@ ScopedMarkTraits* ScopedMarkTraits::instance_ = nullptr;
class MarkAndSweepUtilsMarkTest : public ::testing::Test {
public:
const KStdUnorderedSet<ObjHeader*>& marked() const { return markTraits_.marked(); }
const std_support::unordered_set<ObjHeader*>& marked() const { return markTraits_.marked(); }
auto MarkedMatcher(std::initializer_list<std::reference_wrapper<BaseObject>> expected) {
KStdVector<ObjHeader*> objects;
std_support::vector<ObjHeader*> objects;
for (auto& object : expected) {
objects.push_back(object.get().GetObjHeader());
}
@@ -165,7 +167,7 @@ public:
}
gc::MarkStats Mark(std::initializer_list<std::reference_wrapper<BaseObject>> graySet) {
KStdVector<ObjHeader*> objects;
std_support::vector<ObjHeader*> objects;
for (auto& object : graySet) ScopedMarkTraits::enqueue(objects, object.get().GetObjHeader());
return gc::Mark<ScopedMarkTraits>(objects);
}
@@ -198,10 +198,10 @@ public:
}
}
KStdVector<ObjHeader*> Sweep() {
std_support::vector<ObjHeader*> Sweep() {
gc::SweepExtraObjects<SweepTraits>(extraObjectFactory_);
auto finalizers = gc::Sweep<SweepTraits>(objectFactory_);
KStdVector<ObjHeader*> objects;
std_support::vector<ObjHeader*> objects;
for (auto node : finalizers.IterForTests()) {
objects.push_back(node.GetObjHeader());
}
@@ -209,16 +209,16 @@ public:
return objects;
}
KStdVector<ObjHeader*> Alive() {
KStdVector<ObjHeader*> objects;
std_support::vector<ObjHeader*> Alive() {
std_support::vector<ObjHeader*> objects;
for (auto node : objectFactory_.LockForIter()) {
objects.push_back(node.GetObjHeader());
}
return objects;
}
KStdVector<mm::ExtraObjectData*> AliveExtraObjects() {
KStdVector<mm::ExtraObjectData*> objects;
std_support::vector<mm::ExtraObjectData*> AliveExtraObjects() {
std_support::vector<mm::ExtraObjectData*> objects;
for (auto &node : extraObjectFactory_.LockForIter()) {
objects.push_back(&node);
}
@@ -271,7 +271,7 @@ private:
ObjectFactory::ThreadQueue objectFactoryThreadQueue_{objectFactory_, gc::AlignedAllocator()};
ExtraObjectsDataFactory extraObjectFactory_;
ExtraObjectsDataFactory::ThreadQueue extraObjectFactoryThreadQueue_{extraObjectFactory_};
KStdVector<ObjectFactory::FinalizerQueue> finalizers_;
std_support::vector<ObjectFactory::FinalizerQueue> finalizers_;
};
} // namespace
@@ -6,10 +6,11 @@
#include "GCImpl.hpp"
#include "GC.hpp"
#include "std_support/Memory.hpp"
using namespace kotlin;
gc::GC::ThreadData::ThreadData(GC& gc, mm::ThreadData& threadData) noexcept : impl_(make_unique<Impl>(gc, threadData)) {}
gc::GC::ThreadData::ThreadData(GC& gc, mm::ThreadData& threadData) noexcept : impl_(std_support::make_unique<Impl>(gc, threadData)) {}
gc::GC::ThreadData::~ThreadData() = default;
@@ -49,7 +50,7 @@ void gc::GC::ThreadData::OnStoppedForGC() noexcept {
impl_->gcScheduler().OnStoppedForGC();
}
gc::GC::GC() noexcept : impl_(make_unique<Impl>()) {}
gc::GC::GC() noexcept : impl_(std_support::make_unique<Impl>()) {}
gc::GC::~GC() = default;
@@ -6,6 +6,7 @@
#include "GCImpl.hpp"
#include "GC.hpp"
#include "std_support/Memory.hpp"
using namespace kotlin;
@@ -21,7 +22,7 @@ ALWAYS_INLINE void SafePointRegular(gc::GC::ThreadData& threadData, size_t weigh
} // namespace
gc::GC::ThreadData::ThreadData(GC& gc, mm::ThreadData& threadData) noexcept : impl_(make_unique<Impl>(gc, threadData)) {}
gc::GC::ThreadData::ThreadData(GC& gc, mm::ThreadData& threadData) noexcept : impl_(std_support::make_unique<Impl>(gc, threadData)) {}
gc::GC::ThreadData::~ThreadData() = default;
@@ -61,7 +62,7 @@ void gc::GC::ThreadData::OnStoppedForGC() noexcept {
impl_->gcScheduler().OnStoppedForGC();
}
gc::GC::GC() noexcept : impl_(make_unique<Impl>()) {}
gc::GC::GC() noexcept : impl_(std_support::make_unique<Impl>()) {}
gc::GC::~GC() = default;
@@ -22,6 +22,8 @@
#include "SingleThreadExecutor.hpp"
#include "TestSupport.hpp"
#include "ThreadData.hpp"
#include "std_support/Memory.hpp"
#include "std_support/Vector.hpp"
using namespace kotlin;
@@ -187,8 +189,8 @@ test_support::Object<Payload>& AllocateObjectWithFinalizer(mm::ThreadData& threa
return test_support::Object<Payload>::FromObjHeader(holder.obj());
}
KStdVector<ObjHeader*> Alive(mm::ThreadData& threadData) {
KStdVector<ObjHeader*> objects;
std_support::vector<ObjHeader*> Alive(mm::ThreadData& threadData) {
std_support::vector<ObjHeader*> objects;
for (auto node : threadData.gc().impl().objectFactoryThreadQueue()) {
objects.push_back(node.GetObjHeader());
}
@@ -656,7 +658,7 @@ public:
StackObjectHolder& AddStackRoot() {
RuntimeAssert(std::this_thread::get_id() == executor_.threadId(), "AddStackRoot can only be called in the mutator thread");
auto& context = executor_.context();
auto holder = make_unique<StackObjectHolder>(*context.memory_->memoryState()->GetThreadData());
auto holder = std_support::make_unique<StackObjectHolder>(*context.memory_->memoryState()->GetThreadData());
auto& holderRef = *holder;
context.stackRoots_.push_back(std::move(holder));
return holderRef;
@@ -665,7 +667,7 @@ public:
StackObjectHolder& AddStackRoot(ObjHeader* object) {
RuntimeAssert(std::this_thread::get_id() == executor_.threadId(), "AddStackRoot can only be called in the mutator thread");
auto& context = executor_.context();
auto holder = make_unique<StackObjectHolder>(object);
auto holder = std_support::make_unique<StackObjectHolder>(object);
auto& holderRef = *holder;
context.stackRoots_.push_back(std::move(holder));
return holderRef;
@@ -674,7 +676,7 @@ public:
GlobalObjectHolder& AddGlobalRoot() {
RuntimeAssert(std::this_thread::get_id() == executor_.threadId(), "AddGlobalRoot can only be called in the mutator thread");
auto& context = executor_.context();
auto holder = make_unique<GlobalObjectHolder>(*context.memory_->memoryState()->GetThreadData());
auto holder = std_support::make_unique<GlobalObjectHolder>(*context.memory_->memoryState()->GetThreadData());
auto& holderRef = *holder;
context.globalRoots_.push_back(std::move(holder));
return holderRef;
@@ -683,21 +685,21 @@ public:
GlobalObjectHolder& AddGlobalRoot(ObjHeader* object) {
RuntimeAssert(std::this_thread::get_id() == executor_.threadId(), "AddGlobalRoot can only be called in the mutator thread");
auto& context = executor_.context();
auto holder = make_unique<GlobalObjectHolder>(*context.memory_->memoryState()->GetThreadData(), object);
auto holder = std_support::make_unique<GlobalObjectHolder>(*context.memory_->memoryState()->GetThreadData(), object);
auto& holderRef = *holder;
context.globalRoots_.push_back(std::move(holder));
return holderRef;
}
KStdVector<ObjHeader*> Alive() { return ::Alive(*executor_.context().memory_->memoryState()->GetThreadData()); }
std_support::vector<ObjHeader*> Alive() { return ::Alive(*executor_.context().memory_->memoryState()->GetThreadData()); }
private:
struct Context {
KStdUniquePtr<ScopedMemoryInit> memory_;
KStdVector<KStdUniquePtr<StackObjectHolder>> stackRoots_;
KStdVector<KStdUniquePtr<GlobalObjectHolder>> globalRoots_;
std_support::unique_ptr<ScopedMemoryInit> memory_;
std_support::vector<std_support::unique_ptr<StackObjectHolder>> stackRoots_;
std_support::vector<std_support::unique_ptr<GlobalObjectHolder>> globalRoots_;
Context() : memory_(make_unique<ScopedMemoryInit>()) {
Context() : memory_(std_support::make_unique<ScopedMemoryInit>()) {
// SingleThreadExecutor must work in the runnable state, so that GC does not collect between tasks.
AssertThreadState(memory_->memoryState(), ThreadState::kRunnable);
}
@@ -709,10 +711,10 @@ private:
} // namespace
TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsCollect) {
KStdVector<Mutator> mutators(kDefaultThreadCount);
KStdVector<ObjHeader*> globals(kDefaultThreadCount);
KStdVector<ObjHeader*> locals(kDefaultThreadCount);
KStdVector<ObjHeader*> reachables(kDefaultThreadCount);
std_support::vector<Mutator> mutators(kDefaultThreadCount);
std_support::vector<ObjHeader*> globals(kDefaultThreadCount);
std_support::vector<ObjHeader*> locals(kDefaultThreadCount);
std_support::vector<ObjHeader*> reachables(kDefaultThreadCount);
auto expandRootSet = [&globals, &locals, &reachables](mm::ThreadData& threadData, Mutator& mutator, int i) {
auto& global = mutator.AddGlobalRoot();
@@ -731,7 +733,7 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsCollect) {
.wait();
}
KStdVector<std::future<void>> gcFutures(kDefaultThreadCount);
std_support::vector<std::future<void>> gcFutures(kDefaultThreadCount);
gcFutures[0] = mutators[0].Execute([](mm::ThreadData& threadData, Mutator& mutator) { threadData.gc().ScheduleAndWaitFullGC(); });
@@ -748,7 +750,7 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsCollect) {
future.wait();
}
KStdVector<ObjHeader*> expectedAlive;
std_support::vector<ObjHeader*> expectedAlive;
for (auto& global : globals) {
expectedAlive.push_back(global);
}
@@ -765,10 +767,10 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsCollect) {
}
TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsAllCollect) {
KStdVector<Mutator> mutators(kDefaultThreadCount);
KStdVector<ObjHeader*> globals(kDefaultThreadCount);
KStdVector<ObjHeader*> locals(kDefaultThreadCount);
KStdVector<ObjHeader*> reachables(kDefaultThreadCount);
std_support::vector<Mutator> mutators(kDefaultThreadCount);
std_support::vector<ObjHeader*> globals(kDefaultThreadCount);
std_support::vector<ObjHeader*> locals(kDefaultThreadCount);
std_support::vector<ObjHeader*> reachables(kDefaultThreadCount);
auto expandRootSet = [&globals, &locals, &reachables](mm::ThreadData& threadData, Mutator& mutator, int i) {
auto& global = mutator.AddGlobalRoot();
@@ -787,7 +789,7 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsAllCollect) {
.wait();
}
KStdVector<std::future<void>> gcFutures(kDefaultThreadCount);
std_support::vector<std::future<void>> gcFutures(kDefaultThreadCount);
// TODO: Maybe check that only one GC is performed.
for (int i = 0; i < kDefaultThreadCount; ++i) {
@@ -798,7 +800,7 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsAllCollect) {
future.wait();
}
KStdVector<ObjHeader*> expectedAlive;
std_support::vector<ObjHeader*> expectedAlive;
for (auto& global : globals) {
expectedAlive.push_back(global);
}
@@ -815,10 +817,10 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsAllCollect) {
}
TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsAddToRootSetAfterCollectionRequested) {
KStdVector<Mutator> mutators(kDefaultThreadCount);
KStdVector<ObjHeader*> globals(kDefaultThreadCount);
KStdVector<ObjHeader*> locals(kDefaultThreadCount);
KStdVector<ObjHeader*> reachables(kDefaultThreadCount);
std_support::vector<Mutator> mutators(kDefaultThreadCount);
std_support::vector<ObjHeader*> globals(kDefaultThreadCount);
std_support::vector<ObjHeader*> locals(kDefaultThreadCount);
std_support::vector<ObjHeader*> reachables(kDefaultThreadCount);
auto allocateInHeap = [&globals, &locals, &reachables](mm::ThreadData& threadData, Mutator& mutator, int i) {
auto& global = AllocateObject(threadData);
@@ -852,7 +854,7 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsAddToRootSetAfterCollectionRe
.wait();
}
KStdVector<std::future<void>> gcFutures(kDefaultThreadCount);
std_support::vector<std::future<void>> gcFutures(kDefaultThreadCount);
gcFutures[0] = mutators[0].Execute([](mm::ThreadData& threadData, Mutator& mutator) { threadData.gc().ScheduleAndWaitFullGC(); });
// Spin until thread suspension is requested.
@@ -870,7 +872,7 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsAddToRootSetAfterCollectionRe
future.wait();
}
KStdVector<ObjHeader*> expectedAlive;
std_support::vector<ObjHeader*> expectedAlive;
for (auto& global : globals) {
expectedAlive.push_back(global);
}
@@ -887,10 +889,10 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsAddToRootSetAfterCollectionRe
}
TEST_F(SameThreadMarkAndSweepTest, CrossThreadReference) {
KStdVector<Mutator> mutators(kDefaultThreadCount);
KStdVector<ObjHeader*> globals(kDefaultThreadCount);
KStdVector<ObjHeader*> locals(kDefaultThreadCount);
KStdVector<ObjHeader*> reachables(2 * kDefaultThreadCount);
std_support::vector<Mutator> mutators(kDefaultThreadCount);
std_support::vector<ObjHeader*> globals(kDefaultThreadCount);
std_support::vector<ObjHeader*> locals(kDefaultThreadCount);
std_support::vector<ObjHeader*> reachables(2 * kDefaultThreadCount);
auto expandRootSet = [&globals, &locals, &reachables](mm::ThreadData& threadData, Mutator& mutator, int i) {
auto& global = mutator.AddGlobalRoot();
@@ -916,7 +918,7 @@ TEST_F(SameThreadMarkAndSweepTest, CrossThreadReference) {
.wait();
}
KStdVector<std::future<void>> gcFutures(kDefaultThreadCount);
std_support::vector<std::future<void>> gcFutures(kDefaultThreadCount);
gcFutures[0] = mutators[0].Execute([](mm::ThreadData& threadData, Mutator& mutator) { threadData.gc().ScheduleAndWaitFullGC(); });
@@ -933,7 +935,7 @@ TEST_F(SameThreadMarkAndSweepTest, CrossThreadReference) {
future.wait();
}
KStdVector<ObjHeader*> expectedAlive;
std_support::vector<ObjHeader*> expectedAlive;
for (auto& global : globals) {
expectedAlive.push_back(global);
}
@@ -953,7 +955,7 @@ TEST_F(SameThreadMarkAndSweepTest, CrossThreadReference) {
}
TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsWeaks) {
KStdVector<Mutator> mutators(kDefaultThreadCount);
std_support::vector<Mutator> mutators(kDefaultThreadCount);
ObjHeader* globalRoot = nullptr;
WeakCounter* weak = nullptr;
@@ -977,7 +979,7 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsWeaks) {
mutators[i].Execute([](mm::ThreadData& threadData, Mutator& mutator) {}).wait();
}
KStdVector<std::future<void>> gcFutures(kDefaultThreadCount);
std_support::vector<std::future<void>> gcFutures(kDefaultThreadCount);
gcFutures[0] = mutators[0].Execute([weak](mm::ThreadData& threadData, Mutator& mutator) {
threadData.gc().ScheduleAndWaitFullGC();
@@ -1005,11 +1007,11 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsWeaks) {
}
TEST_F(SameThreadMarkAndSweepTest, NewThreadsWhileRequestingCollection) {
KStdVector<Mutator> mutators(kDefaultThreadCount);
KStdVector<ObjHeader*> globals(2 * kDefaultThreadCount);
KStdVector<ObjHeader*> locals(2 * kDefaultThreadCount);
KStdVector<ObjHeader*> reachables(2 * kDefaultThreadCount);
KStdVector<ObjHeader*> unreachables(2 * kDefaultThreadCount);
std_support::vector<Mutator> mutators(kDefaultThreadCount);
std_support::vector<ObjHeader*> globals(2 * kDefaultThreadCount);
std_support::vector<ObjHeader*> locals(2 * kDefaultThreadCount);
std_support::vector<ObjHeader*> reachables(2 * kDefaultThreadCount);
std_support::vector<ObjHeader*> unreachables(2 * kDefaultThreadCount);
auto expandRootSet = [&globals, &locals, &reachables, &unreachables](mm::ThreadData& threadData, Mutator& mutator, int i) {
auto& global = mutator.AddGlobalRoot();
@@ -1029,7 +1031,7 @@ TEST_F(SameThreadMarkAndSweepTest, NewThreadsWhileRequestingCollection) {
.wait();
}
KStdVector<std::future<void>> gcFutures(kDefaultThreadCount);
std_support::vector<std::future<void>> gcFutures(kDefaultThreadCount);
gcFutures[0] = mutators[0].Execute([](mm::ThreadData& threadData, Mutator& mutator) { threadData.gc().ScheduleAndWaitFullGC(); });
@@ -1038,8 +1040,8 @@ TEST_F(SameThreadMarkAndSweepTest, NewThreadsWhileRequestingCollection) {
}
// Now start attaching new threads.
KStdVector<Mutator> newMutators(kDefaultThreadCount);
KStdVector<std::future<void>> attachFutures(kDefaultThreadCount);
std_support::vector<Mutator> newMutators(kDefaultThreadCount);
std_support::vector<std::future<void>> attachFutures(kDefaultThreadCount);
for (int i = 0; i < kDefaultThreadCount; ++i) {
attachFutures[i] = newMutators[i].Execute([i, expandRootSet](mm::ThreadData& threadData, Mutator& mutator) { expandRootSet(threadData, mutator, i + kDefaultThreadCount); });
@@ -1063,7 +1065,7 @@ TEST_F(SameThreadMarkAndSweepTest, NewThreadsWhileRequestingCollection) {
// Old mutators don't even see alive objects from the new threads yet (as the latter ones have not published anything).
KStdVector<ObjHeader*> expectedAlive;
std_support::vector<ObjHeader*> expectedAlive;
for (int i = 0; i < kDefaultThreadCount; ++i) {
expectedAlive.push_back(globals[i]);
expectedAlive.push_back(locals[i]);
@@ -1075,7 +1077,7 @@ TEST_F(SameThreadMarkAndSweepTest, NewThreadsWhileRequestingCollection) {
}
for (int i = 0; i < kDefaultThreadCount; ++i) {
KStdVector<ObjHeader*> aliveForThisThread(expectedAlive.begin(), expectedAlive.end());
std_support::vector<ObjHeader*> aliveForThisThread(expectedAlive.begin(), expectedAlive.end());
aliveForThisThread.push_back(globals[kDefaultThreadCount + i]);
aliveForThisThread.push_back(locals[kDefaultThreadCount + i]);
aliveForThisThread.push_back(reachables[kDefaultThreadCount + i]);
@@ -1087,7 +1089,7 @@ TEST_F(SameThreadMarkAndSweepTest, NewThreadsWhileRequestingCollection) {
TEST_F(SameThreadMarkAndSweepTest, FreeObjectWithFreeWeakReversedOrder) {
KStdVector<Mutator> mutators(2);
std_support::vector<Mutator> mutators(2);
std::atomic<test_support::Object<Payload>*> object1 = nullptr;
std::atomic<WeakCounter*> weak = nullptr;
std::atomic<bool> done = false;
@@ -20,6 +20,7 @@
#include "Porting.h"
#include "Runtime.h"
#include "Types.h"
#include "std_support/CStdlib.hpp"
#ifdef KONAN_ANDROID
@@ -44,6 +45,8 @@
# define LOGV(...) ((void)0)
#endif
using namespace kotlin;
//--- main --------------------------------------------------------------------//
namespace {
@@ -215,7 +218,7 @@ extern "C" void RUNTIME_USED Konan_main(
ANativeActivity* activity, void* savedState, size_t savedStateSize) {
bool launchThread = activity->instance == nullptr;
if (launchThread) {
launcherState = (LauncherState*)konan::calloc(sizeof(LauncherState), 1);
launcherState = (LauncherState*)std_support::calloc(sizeof(LauncherState), 1);
launcherState->nativeActivityState = {activity, savedState, savedStateSize, nullptr};
activity->instance = launcherState;
activity->callbacks->onDestroy = onDestroy;
@@ -20,9 +20,12 @@
#include "KString.h"
#include "Types.h"
#include "Worker.h"
#include "std_support/CStdlib.hpp"
#include "launcher.h"
using namespace kotlin;
//--- Setup args --------------------------------------------------------------//
OBJ_GETTER(setupArgs, int argc, const char** argv) {
@@ -77,9 +80,9 @@ extern "C" int Konan_js_arg_size(int index);
extern "C" int Konan_js_fetch_arg(int index, char* ptr);
extern "C" RUNTIME_USED int Konan_js_main(int argc, int memoryDeInit) {
char** argv = (char**)konan::calloc(1, argc);
char** argv = (char**)std_support::calloc(1, argc);
for (int i = 0; i< argc; ++i) {
argv[i] = (char*)konan::calloc(1, Konan_js_arg_size(i));
argv[i] = (char*)std_support::calloc(1, Konan_js_arg_size(i));
Konan_js_fetch_arg(i, argv[i]);
}
return Init_and_run_start(argc, (const char**)argv, memoryDeInit);
@@ -17,7 +17,6 @@
#define WITH_WORKERS 1
#endif
#include "Alloc.h"
#include "Atomic.h"
#include "KAssert.h"
#include "Memory.h"
@@ -25,6 +24,11 @@
#include "Natives.h"
#include "Porting.h"
#include "Types.h"
#include "std_support/Deque.hpp"
#include "std_support/New.hpp"
#include "std_support/UnorderedMap.hpp"
#include "std_support/UnorderedSet.hpp"
#include "std_support/Vector.hpp"
#if WITH_WORKERS
#include <pthread.h>
@@ -42,6 +46,8 @@
#define COLLECTOR_LOG(...)
#endif
using namespace kotlin;
/**
* Theory of operations:
*
@@ -124,8 +130,8 @@ class CyclicCollector {
int32_t lastTick_;
int64_t lastTimestampUs_;
void* mainWorker_;
KStdUnorderedSet<ObjHeader*> rootset_;
KStdUnorderedSet<ObjHeader*> toRelease_;
std_support::unordered_set<ObjHeader*> rootset_;
std_support::unordered_set<ObjHeader*> toRelease_;
public:
CyclicCollector() {
@@ -168,9 +174,9 @@ class CyclicCollector {
void gcProcessor() {
{
Locker locker(&lock_);
KStdDeque<ObjHeader*> toVisit;
KStdUnorderedSet<ObjHeader*> visited;
KStdUnorderedMap<ObjHeader*, int> sideRefCounts;
std_support::deque<ObjHeader*> toVisit;
std_support::unordered_set<ObjHeader*> visited;
std_support::unordered_map<ObjHeader*, int> sideRefCounts;
int restartCount = 0;
while (!terminateCollector_) {
CHECK_CALL(pthread_cond_wait(&cond_, &lock_), "Cannot wait collector condition");
@@ -382,7 +388,7 @@ class CyclicCollector {
// We are not doing that on the UI thread, as taking lock is slow, unless
// it happens on deinit of the collector or if there are no other workers.
if ((atomicGet(&pendingRelease_) != 0) && ((worker != mainWorker_) || (currentAliveWorkers_ == 1))) {
KStdVector<ObjHeader*> heapRefsToRelease;
std_support::vector<ObjHeader*> heapRefsToRelease;
{
suggestLockRelease();
@@ -445,7 +451,7 @@ CyclicCollector* cyclicCollector = nullptr;
void cyclicInit() {
#if WITH_WORKERS
RuntimeAssert(cyclicCollector == nullptr, "Must be not yet inited");
cyclicCollector = konanConstructInstance<CyclicCollector>();
cyclicCollector = new (std_support::kalloc) CyclicCollector();
#endif
}
@@ -456,7 +462,7 @@ void cyclicDeinit(bool enabled) {
local->terminate(enabled);
cyclicCollector = nullptr;
// Workaround data race with threads non-atomically reading and then using [cyclicCollector].
// konanDestructInstance(local);
// std_support::kdelete(local);
// Note: memory leaks here indeed, but usually it happens once per application.
// Make best effort to clean some memory:
local->clear();
@@ -31,7 +31,6 @@
#define USE_CYCLE_DETECTOR 1
#endif
#include "Alloc.h"
#include "KAssert.h"
#include "Atomic.h"
#include "Cleaner.h"
@@ -53,7 +52,13 @@
#include "Utils.hpp"
#include "WorkerBoundReference.h"
#include "Weak.h"
#include "std_support/CStdlib.hpp"
#include "std_support/Deque.hpp"
#include "std_support/List.hpp"
#include "std_support/New.hpp"
#include "std_support/UnorderedMap.hpp"
#include "std_support/UnorderedSet.hpp"
#include "std_support/Vector.hpp"
#ifdef KONAN_OBJC_INTEROP
#include "ObjCMMAPI.h"
@@ -134,15 +139,15 @@ constexpr size_t kGcCollectCyclesMinimumDuration = 200;
#endif // USE_GC
typedef KStdUnorderedSet<ContainerHeader*> ContainerHeaderSet;
typedef KStdVector<ContainerHeader*> ContainerHeaderList;
typedef KStdDeque<ContainerHeader*> ContainerHeaderDeque;
typedef KStdVector<KRef> KRefList;
typedef KStdVector<KRef*> KRefPtrList;
typedef KStdUnorderedSet<KRef> KRefSet;
typedef KStdUnorderedMap<KRef, KInt> KRefIntMap;
typedef KStdDeque<KRef> KRefDeque;
typedef KStdDeque<KRefList> KRefListDeque;
typedef std_support::unordered_set<ContainerHeader*> ContainerHeaderSet;
typedef std_support::vector<ContainerHeader*> ContainerHeaderList;
typedef std_support::deque<ContainerHeader*> ContainerHeaderDeque;
typedef std_support::vector<KRef> KRefList;
typedef std_support::vector<KRef*> KRefPtrList;
typedef std_support::unordered_set<KRef> KRefSet;
typedef std_support::unordered_map<KRef, KInt> KRefIntMap;
typedef std_support::deque<KRef> KRefDeque;
typedef std_support::deque<KRefList> KRefListDeque;
// A little hack that allows to enable -O2 optimizations
// Prevents clang from replacing FrameOverlay struct
@@ -192,11 +197,11 @@ class ScopedRefHolder : private kotlin::MoveOnly {
struct CycleDetectorRootset {
// Orders roots.
KStdVector<KRef> roots;
std_support::vector<KRef> roots;
// Pins a state of each root.
KStdUnorderedMap<KRef, KStdVector<KRef>> rootToFields;
std_support::unordered_map<KRef, std_support::vector<KRef>> rootToFields;
// Holding roots and their fields to avoid GC-ing them.
KStdVector<ScopedRefHolder> heldRefs;
std_support::vector<ScopedRefHolder> heldRefs;
};
class CycleDetector : private kotlin::Pinned {
@@ -247,9 +252,9 @@ class CycleDetector : private kotlin::Pinned {
}
kotlin::SpinLock<kotlin::MutexThreadStateHandling::kIgnore> lock_;
using CandidateList = KStdList<KRef>;
using CandidateList = std_support::list<KRef>;
CandidateList candidateList_;
KStdUnorderedMap<KRef, CandidateList::iterator> candidateInList_;
std_support::unordered_map<KRef, CandidateList::iterator> candidateInList_;
};
#endif // USE_CYCLE_DETECTOR
@@ -268,7 +273,7 @@ public:
// Free per container type counters.
uint64_t objectAllocs[6];
// Histogram of allocation size distribution.
KStdUnorderedMap<int, int>* allocationHistogram;
std_support::unordered_map<int, int>* allocationHistogram;
// Number of allocation cache hits.
int allocCacheHit;
// Number of allocation cache misses.
@@ -292,13 +297,13 @@ public:
memset(containerAllocs, 0, sizeof(containerAllocs));
memset(objectAllocs, 0, sizeof(objectAllocs));
memset(updateCounters, 0, sizeof(updateCounters));
allocationHistogram = konanConstructInstance<KStdUnorderedMap<int, int>>();
allocationHistogram = new (std_support::kalloc) std_support::unordered_map<int, int>();
allocCacheHit = 0;
allocCacheMiss = 0;
}
void deinit() {
konanDestructInstance(allocationHistogram);
std_support::kdelete(allocationHistogram);
allocationHistogram = nullptr;
}
@@ -402,7 +407,7 @@ public:
konan::consolePrintf("\n");
konan::consolePrintf("Allocation histogram:\n");
KStdVector<int> keys(allocationHistogram->size());
std_support::vector<int> keys(allocationHistogram->size());
int index = 0;
for (auto& it : *allocationHistogram) {
keys[index++] = it.first;
@@ -511,7 +516,7 @@ void ObjHeader::SetAssociatedObject(void* obj) {
class ForeignRefManager {
public:
static ForeignRefManager* create() {
ForeignRefManager* result = konanConstructInstance<ForeignRefManager>();
ForeignRefManager* result = new (std_support::kalloc) ForeignRefManager();
result->addRef();
return result;
}
@@ -528,7 +533,7 @@ class ForeignRefManager {
// so it can process the queue pretending like it takes ownership of all its objects:
this->processAbandoned();
konanDestructInstance(this);
std_support::kdelete(this);
}
}
@@ -541,14 +546,14 @@ class ForeignRefManager {
return false;
}
konanDestructInstance(this);
std_support::kdelete(this);
}
return true;
}
void enqueueReleaseRef(ObjHeader* obj) {
ListNode* newListNode = konanConstructInstance<ListNode>();
ListNode* newListNode = new (std_support::kalloc) ListNode();
newListNode->obj = obj;
while (true) {
ListNode* next = this->releaseList;
@@ -571,7 +576,7 @@ class ForeignRefManager {
while (toProcess != nullptr) {
process(toProcess->obj);
ListNode* next = toProcess->next;
konanDestructInstance(toProcess);
std_support::kdelete(toProcess);
toProcess = next;
}
}
@@ -616,11 +621,11 @@ class ThreadLocalStorage {
public:
using Key = void**;
void Init() noexcept { map_ = konanConstructInstance<Map>(); }
void Init() noexcept { map_ = new (std_support::kalloc) Map(); }
void Deinit() noexcept {
RuntimeAssert(map_->size() == 0, "Must be already cleared");
konanDestructInstance(map_);
std_support::kdelete(map_);
}
void Add(Key key, int size) noexcept {
@@ -636,7 +641,7 @@ public:
void Commit() noexcept {
RuntimeAssert(storage_ == nullptr, "Cannot commit storage twice");
storage_ = reinterpret_cast<KRef*>(konanAllocMemory(size_ * sizeof(KRef)));
storage_ = reinterpret_cast<KRef*>(std_support::calloc(size_, sizeof(KRef)));
}
void Clear() noexcept {
@@ -644,7 +649,7 @@ public:
for (int i = 0; i < size_; ++i) {
UpdateHeapRef(storage_ + i, nullptr);
}
konanFreeMemory(storage_);
std_support::free(storage_);
map_->clear();
}
@@ -669,7 +674,7 @@ private:
int size;
};
using Map = KStdUnorderedMap<Key, Entry>;
using Map = std_support::unordered_map<Key, Entry>;
Map* map_ = nullptr;
KRef* storage_ = nullptr;
@@ -726,7 +731,7 @@ struct MemoryState {
#endif // USE_GC
// A stack of initializing singletons.
KStdVector<std::pair<ObjHeader**, ObjHeader*>> initializingSingletons;
std_support::vector<std::pair<ObjHeader**, ObjHeader*>> initializingSingletons;
bool isMainThread = false;
@@ -767,9 +772,9 @@ namespace {
#if TRACE_MEMORY
#define INIT_TRACE(state) \
memoryState->containers = konanConstructInstance<ContainerHeaderSet>();
memoryState->containers = new (std_support::kalloc) ContainerHeaderSet();
#define DEINIT_TRACE(state) \
konanDestructInstance(memoryState->containers); \
std_support::kdelete(memoryState->containers); \
memoryState->containers = nullptr;
#else
#define INIT_TRACE(state)
@@ -1069,7 +1074,7 @@ ContainerHeader* allocContainer(MemoryState* state, size_t size) {
if (state != nullptr)
state->allocSinceLastGc += size;
#endif
result = konanConstructSizedInstance<ContainerHeader>(alignUp(size, kObjectAlignment));
result = new (std_support::calloc(1, alignUp(size, kObjectAlignment))) ContainerHeader();
atomicAdd(&allocCount, 1);
}
if (state != nullptr) {
@@ -1081,7 +1086,7 @@ ContainerHeader* allocContainer(MemoryState* state, size_t size) {
return result;
}
ContainerHeader* allocAggregatingFrozenContainer(KStdVector<ContainerHeader*>& containers) {
ContainerHeader* allocAggregatingFrozenContainer(std_support::vector<ContainerHeader*>& containers) {
auto componentSize = containers.size();
auto* superContainer = allocContainer(memoryState, sizeof(ContainerHeader) + sizeof(void*) * componentSize);
auto* place = reinterpret_cast<ContainerHeader**>(superContainer + 1);
@@ -1110,7 +1115,7 @@ void processFinalizerQueue(MemoryState* state) {
state->containers->erase(container);
#endif
CONTAINER_DESTROY_EVENT(state, container)
konanFreeMemory(container);
std_support::free(container);
atomicAdd(&allocCount, -1);
}
RuntimeAssert(state->finalizerQueueSize == 0, "Queue must be empty here");
@@ -1151,7 +1156,7 @@ void scheduleDestroyContainer(MemoryState* state, ContainerHeader* container) {
processFinalizerQueue(state);
}
#else
konanFreeMemory(container);
std_support::free(container);
atomicAdd(&allocCount, -1);
CONTAINER_DESTROY_EVENT(state, container);
#endif
@@ -1229,7 +1234,7 @@ void freeContainer(ContainerHeader* container) {
* When we see GREY during DFS, it means we see cycle.
*/
void depthFirstTraversal(ContainerHeader* start, bool* hasCycles,
KRef* firstBlocker, KStdVector<ContainerHeader*>* order) {
KRef* firstBlocker, std_support::vector<ContainerHeader*>* order) {
ContainerHeaderDeque toVisit;
toVisit.push_back(start);
start->setSeen();
@@ -1277,9 +1282,9 @@ void depthFirstTraversal(ContainerHeader* start, bool* hasCycles,
}
void traverseStronglyConnectedComponent(ContainerHeader* start,
KStdUnorderedMap<ContainerHeader*,
KStdVector<ContainerHeader*>> const* reversedEdges,
KStdVector<ContainerHeader*>* component) {
std_support::unordered_map<ContainerHeader*,
std_support::vector<ContainerHeader*>> const* reversedEdges,
std_support::vector<ContainerHeader*>* component) {
ContainerHeaderDeque toVisit;
toVisit.push_back(start);
start->mark();
@@ -1447,8 +1452,8 @@ void dumpObject(ObjHeader* ref, int indent) {
typeInfo->relativeName_ != nullptr ? CreateCStringFromString(typeInfo->relativeName_) : nullptr;
MEMORY_LOG("%p %s.%s\n", ref,
packageName ? packageName : "<unknown>", relativeName ? relativeName : "<unknown>");
if (packageName) konan::free(packageName);
if (relativeName) konan::free(relativeName);
if (packageName) std_support::free(packageName);
if (relativeName) std_support::free(relativeName);
}
void dumpContainerContent(ContainerHeader* container) {
@@ -1762,7 +1767,7 @@ inline ArenaContainer* initedArena(ObjHeader** auxSlot) {
auto frame = asFrameOverlay(auxSlot);
auto arena = reinterpret_cast<ArenaContainer*>(frame->arena);
if (!arena) {
arena = konanConstructInstance<ArenaContainer>();
arena = new (std_support::kalloc) ArenaContainer();
MEMORY_LOG("Initializing arena in %p\n", frame)
arena->Init();
frame->arena = arena;
@@ -2055,14 +2060,14 @@ MemoryState* initMemory(bool firstRuntime) {
"Layout mismatch");
RuntimeAssert(sizeof(FrameOverlay) % sizeof(ObjHeader**) == 0, "Frame overlay should contain only pointers");
RuntimeAssert(memoryState == nullptr, "memory state must be clear");
memoryState = konanConstructInstance<MemoryState>();
memoryState = new (std_support::kalloc) MemoryState();
INIT_EVENT(memoryState)
#if USE_GC
memoryState->toFree = konanConstructInstance<ContainerHeaderList>();
memoryState->roots = konanConstructInstance<ContainerHeaderList>();
memoryState->toFree = new (std_support::kalloc) ContainerHeaderList();
memoryState->roots = new (std_support::kalloc) ContainerHeaderList();
memoryState->gcInProgress = false;
memoryState->gcSuspendCount = 0;
memoryState->toRelease = konanConstructInstance<ContainerHeaderList>();
memoryState->toRelease = new (std_support::kalloc) ContainerHeaderList();
initGcThreshold(memoryState, kGcThreshold);
initGcCollectCyclesThreshold(memoryState, kMaxToFreeSizeThreshold);
memoryState->allocSinceLastGcThreshold = kMaxGcAllocThreshold;
@@ -2121,9 +2126,9 @@ void deinitMemory(MemoryState* memoryState, bool destroyRuntime) {
} while (memoryState->toRelease->size() > 0 || !memoryState->foreignRefManager->tryReleaseRefOwned());
RuntimeAssert(memoryState->toFree->size() == 0, "Some memory have not been released after GC");
RuntimeAssert(memoryState->toRelease->size() == 0, "Some memory have not been released after GC");
konanDestructInstance(memoryState->toFree);
konanDestructInstance(memoryState->roots);
konanDestructInstance(memoryState->toRelease);
std_support::kdelete(memoryState->toFree);
std_support::kdelete(memoryState->roots);
std_support::kdelete(memoryState->toRelease);
memoryState->tls.Deinit();
RuntimeAssert(memoryState->finalizerQueue == nullptr, "Finalizer queue must be empty");
RuntimeAssert(memoryState->finalizerQueueSize == 0, "Finalizer queue must be empty");
@@ -2151,7 +2156,7 @@ void deinitMemory(MemoryState* memoryState, bool destroyRuntime) {
PRINT_EVENT(memoryState)
DEINIT_EVENT(memoryState)
konanFreeMemory(memoryState);
std_support::free(memoryState);
::memoryState = nullptr;
}
@@ -2618,9 +2623,9 @@ void stopGC() {
if (memoryState->toRelease != nullptr) {
memoryState->gcSuspendCount = 0;
garbageCollect(memoryState, true);
konanDestructInstance(memoryState->toRelease);
konanDestructInstance(memoryState->toFree);
konanDestructInstance(memoryState->roots);
std_support::kdelete(memoryState->toRelease);
std_support::kdelete(memoryState->toFree);
std_support::kdelete(memoryState->roots);
memoryState->toRelease = nullptr;
memoryState->toFree = nullptr;
memoryState->roots = nullptr;
@@ -2630,9 +2635,9 @@ void stopGC() {
void startGC() {
GC_LOG("startGC\n")
if (memoryState->toFree == nullptr) {
memoryState->toFree = konanConstructInstance<ContainerHeaderList>();
memoryState->toRelease = konanConstructInstance<ContainerHeaderList>();
memoryState->roots = konanConstructInstance<ContainerHeaderList>();
memoryState->toFree = new (std_support::kalloc) ContainerHeaderList();
memoryState->toRelease = new (std_support::kalloc) ContainerHeaderList();
memoryState->roots = new (std_support::kalloc) ContainerHeaderList();
memoryState->gcSuspendCount = 0;
}
}
@@ -2786,7 +2791,7 @@ bool clearSubgraphReferences(ObjHeader* root, bool checked) {
}
void freezeAcyclic(ContainerHeader* rootContainer, ContainerHeaderSet* newlyFrozen) {
KStdDeque<ContainerHeader*> queue;
std_support::deque<ContainerHeader*> queue;
queue.push_back(rootContainer);
while (!queue.empty()) {
ContainerHeader* current = queue.front();
@@ -2811,17 +2816,17 @@ void freezeAcyclic(ContainerHeader* rootContainer, ContainerHeaderSet* newlyFroz
}
void freezeCyclic(ObjHeader* root,
const KStdVector<ContainerHeader*>& order,
const std_support::vector<ContainerHeader*>& order,
ContainerHeaderSet* newlyFrozen) {
KStdUnorderedMap<ContainerHeader*, KStdVector<ContainerHeader*>> reversedEdges;
KStdDeque<ObjHeader*> queue;
std_support::unordered_map<ContainerHeader*, std_support::vector<ContainerHeader*>> reversedEdges;
std_support::deque<ObjHeader*> queue;
queue.push_back(root);
while (!queue.empty()) {
ObjHeader* current = queue.front();
queue.pop_front();
ContainerHeader* currentContainer = containerFor(current);
currentContainer->unMark();
reversedEdges.emplace(currentContainer, KStdVector<ContainerHeader*>(0));
reversedEdges.emplace(currentContainer, std_support::vector<ContainerHeader*>(0));
traverseContainerReferredObjects(currentContainer, [current, currentContainer, &queue, &reversedEdges](ObjHeader* obj) {
ContainerHeader* objContainer = containerFor(obj);
if (canFreeze(objContainer)) {
@@ -2829,19 +2834,19 @@ void freezeCyclic(ObjHeader* root,
queue.push_back(obj);
// We ignore references from FreezableAtomicsReference during condensation, to avoid KT-33824.
if (!isFreezableAtomic(current))
reversedEdges.emplace(objContainer, KStdVector<ContainerHeader*>(0)).
reversedEdges.emplace(objContainer, std_support::vector<ContainerHeader*>(0)).
first->second.push_back(currentContainer);
}
});
}
KStdVector<KStdVector<ContainerHeader*>> components;
std_support::vector<std_support::vector<ContainerHeader*>> components;
MEMORY_LOG("Condensation:\n");
// Enumerate in the topological order.
for (auto it = order.rbegin(); it != order.rend(); ++it) {
auto* container = *it;
if (container->marked()) continue;
KStdVector<ContainerHeader*> component;
std_support::vector<ContainerHeader*> component;
traverseStronglyConnectedComponent(container, &reversedEdges, &component);
MEMORY_LOG("SCC:\n");
#if TRACE_MEMORY
@@ -2896,8 +2901,8 @@ void freezeCyclic(ObjHeader* root,
}
void runFreezeHooksRecursive(ObjHeader* root) {
KStdUnorderedSet<KRef> seen;
KStdVector<KRef> toVisit;
std_support::unordered_set<KRef> seen;
std_support::vector<KRef> toVisit;
seen.insert(root);
toVisit.push_back(root);
while (!toVisit.empty()) {
@@ -2964,7 +2969,7 @@ void freezeSubgraph(ObjHeader* root) {
bool hasCycles = false;
KRef firstBlocker = root->has_meta_object() && ((root->meta_object()->flags_ & MF_NEVER_FROZEN) != 0) ?
root : nullptr;
KStdVector<ContainerHeader*> order;
std_support::vector<ContainerHeader*> order;
depthFirstTraversal(rootContainer, &hasCycles, &firstBlocker, &order);
if (firstBlocker != nullptr) {
MEMORY_LOG("See freeze blocker for %p: %p\n", root, firstBlocker)
@@ -3044,7 +3049,7 @@ CycleDetectorRootset CycleDetector::collectRootset() {
return rootset;
}
KStdVector<KRef> findCycleWithDFS(KRef root, const CycleDetectorRootset& rootset) {
std_support::vector<KRef> findCycleWithDFS(KRef root, const CycleDetectorRootset& rootset) {
auto traverseFields = [&rootset](KRef obj, auto process) {
auto it = rootset.rootToFields.find(obj);
// If obj is in the rootset, use it's pinned state.
@@ -3061,8 +3066,8 @@ KStdVector<KRef> findCycleWithDFS(KRef root, const CycleDetectorRootset& rootset
kotlin::traverseReferredObjects(obj, process);
};
KStdVector<KStdVector<KRef>> toVisit;
auto appendFieldsToVisit = [&toVisit, &traverseFields](KRef obj, const KStdVector<KRef>& currentPath) {
std_support::vector<std_support::vector<KRef>> toVisit;
auto appendFieldsToVisit = [&toVisit, &traverseFields](KRef obj, const std_support::vector<KRef>& currentPath) {
traverseFields(obj, [&toVisit, &currentPath](KRef field) {
auto path = currentPath;
path.push_back(field);
@@ -3072,10 +3077,10 @@ KStdVector<KRef> findCycleWithDFS(KRef root, const CycleDetectorRootset& rootset
appendFieldsToVisit(root, KRefList(1, root));
KStdUnorderedSet<KRef> seen;
std_support::unordered_set<KRef> seen;
seen.insert(root);
while (!toVisit.empty()) {
KStdVector<KRef> currentPath = std::move(toVisit.back());
std_support::vector<KRef> currentPath = std::move(toVisit.back());
toVisit.pop_back();
KRef node = currentPath[currentPath.size() - 1];
@@ -3108,7 +3113,7 @@ OBJ_GETTER(createAndFillArray, const C& container) {
OBJ_GETTER0(detectCyclicReferences) {
auto rootset = CycleDetector::collectRootset();
KStdVector<KRef> cyclic;
std_support::vector<KRef> cyclic;
for (KRef root: rootset.roots) {
if (!findCycleWithDFS(root, rootset).empty()) {
@@ -3145,7 +3150,7 @@ MetaObjHeader* ObjHeader::createMetaObject(ObjHeader* object) {
}
#endif
MetaObjHeader* meta = konanConstructInstance<MetaObjHeader>();
MetaObjHeader* meta = new (std_support::kalloc) MetaObjHeader();
meta->typeInfo_ = typeInfo;
#if KONAN_NO_THREADS
*location = reinterpret_cast<TypeInfo*>(meta);
@@ -3153,7 +3158,7 @@ MetaObjHeader* ObjHeader::createMetaObject(ObjHeader* object) {
TypeInfo* old = __sync_val_compare_and_swap(location, typeInfo, reinterpret_cast<TypeInfo*>(meta));
if (old != typeInfo) {
// Someone installed a new meta-object since the check.
konanFreeMemory(meta);
std_support::free(meta);
meta = reinterpret_cast<MetaObjHeader*>(old);
}
#endif
@@ -3173,7 +3178,7 @@ void ObjHeader::destroyMetaObject(ObjHeader* object) {
Kotlin_ObjCExport_detachAndReleaseAssociatedObject(meta->associatedObject_);
#endif
konanFreeMemory(meta);
std_support::free(meta);
}
void ObjectContainer::Init(MemoryState* state, const TypeInfo* typeInfo) {
@@ -3223,7 +3228,7 @@ void ArenaContainer::Deinit() {
while (chunk != nullptr) {
auto toRemove = chunk;
chunk = chunk->next;
konanFreeMemory(toRemove);
std_support::free(toRemove);
}
}
@@ -3231,7 +3236,7 @@ bool ArenaContainer::allocContainer(container_size_t minSize) {
auto size = minSize + sizeof(ContainerHeader) + sizeof(ContainerChunk);
size = alignUp(size, kContainerAlignment);
// TODO: keep simple cache of container chunks.
ContainerChunk* result = konanConstructSizedInstance<ContainerChunk>(size);
ContainerChunk* result = new (std_support::calloc(1, size)) ContainerChunk();
RuntimeCheck(result != nullptr, "Cannot alloc memory");
if (result == nullptr) return false;
result->next = currentChunk_;
@@ -1,61 +0,0 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
#pragma once
#include <cstddef>
#include <new>
#include <utility>
#include "std_support/CStdlib.hpp"
#include "std_support/New.hpp"
namespace konan {
inline void* calloc(size_t count, size_t size) {
return kotlin::std_support::calloc(count, size);
}
inline void* calloc_aligned(size_t count, size_t size, size_t alignment) {
return kotlin::std_support::aligned_calloc(alignment, count, size);
}
inline void free(void* ptr) {
kotlin::std_support::free(ptr);
}
} // namespace konan
inline void* konanAllocMemory(size_t size) {
return konan::calloc(1, size);
}
inline void* konanAllocAlignedMemory(size_t size, size_t alignment) {
return konan::calloc_aligned(1, size, alignment);
}
inline void konanFreeMemory(void* memory) {
konan::free(memory);
}
template<typename T>
inline T* konanAllocArray(size_t length) {
return reinterpret_cast<T*>(konanAllocMemory(length * sizeof(T)));
}
template <typename T, typename ...A>
inline T* konanConstructInstance(A&& ...args) {
return new (kotlin::std_support::kalloc) T(std::forward<A>(args)...);
}
template <typename T, typename ...A>
inline T* konanConstructSizedInstance(size_t size, A&& ...args) {
return new (konanAllocMemory(size)) T(::std::forward<A>(args)...);
}
template <typename T>
inline void konanDestructInstance(T* instance) {
kotlin::std_support::kdelete(instance);
}
@@ -14,6 +14,7 @@
#include "TestSupport.hpp"
#include "TestSupportCompilerGenerated.hpp"
#include "Types.h"
#include "std_support/Vector.hpp"
using namespace kotlin;
using namespace kotlin::test_support;
@@ -39,7 +40,7 @@ TEST_F(CleanerTest, ConcurrentCreation) {
int startedThreads = 0;
bool allowRunning = false;
KStdVector<std::future<KInt>> futures;
std_support::vector<std::future<KInt>> futures;
for (int i = 0; i < threadCount; ++i) {
auto future = std::async(std::launch::async, [&startedThreads, &allowRunning]() {
// Thread state switching requires initilized memory subsystem.
@@ -54,7 +55,7 @@ TEST_F(CleanerTest, ConcurrentCreation) {
while (atomicGet(&startedThreads) != threadCount) {
}
atomicSet(&allowRunning, true);
KStdVector<KInt> values;
std_support::vector<KInt> values;
for (auto& future : futures) {
values.push_back(future.get());
}
@@ -18,6 +18,7 @@
#include "ClockTestSupport.hpp"
#include "ScopedThread.hpp"
#include "TestSupport.hpp"
#include "std_support/Vector.hpp"
using namespace kotlin;
@@ -1035,7 +1036,7 @@ TEST(ManualClockTest, ConcurrentSleepUntil) {
test_support::manual_clock::reset();
constexpr auto threadCount = kDefaultThreadCount;
KStdVector<ScopedThread> threads;
std_support::vector<ScopedThread> threads;
std::atomic<bool> run = false;
std::atomic<int> ready = 0;
for (int i = 0; i < threadCount; ++i) {
@@ -1060,7 +1061,7 @@ TEST(ManualClockTest, ConcurrentWaits) {
test_support::manual_clock::reset();
constexpr auto threadCount = kDefaultThreadCount;
KStdVector<ScopedThread> threads;
std_support::vector<ScopedThread> threads;
std::mutex mutex;
std::condition_variable cv;
std::condition_variable_any cvAny;
@@ -14,4 +14,4 @@ std::atomic<test_support::manual_clock::time_point> test_support::manual_clock::
std::mutex test_support::manual_clock::pendingWaitsMutex_;
// static
KStdOrderedMultiset<test_support::manual_clock::time_point> test_support::manual_clock::pendingWaits_;
std_support::multiset<test_support::manual_clock::time_point> test_support::manual_clock::pendingWaits_;
@@ -11,8 +11,9 @@
#include "gtest/gtest.h"
#include "Types.h"
#include "KAssert.h"
#include "Utils.hpp"
#include "std_support/Set.hpp"
namespace kotlin::test_support {
@@ -88,9 +89,9 @@ private:
private:
friend class manual_clock;
explicit PendingWaitRegistration(KStdOrderedMultiset<time_point>::iterator it) noexcept : it_(it) {}
explicit PendingWaitRegistration(std_support::multiset<time_point>::iterator it) noexcept : it_(it) {}
KStdOrderedMultiset<time_point>::iterator it_;
std_support::multiset<time_point>::iterator it_;
};
template <typename Rep, typename Period>
@@ -103,7 +104,7 @@ private:
static std::atomic<time_point> now_;
static std::mutex pendingWaitsMutex_;
static KStdOrderedMultiset<time_point> pendingWaits_;
static std_support::multiset<time_point> pendingWaits_;
};
} // namespace kotlin::test_support
@@ -25,9 +25,13 @@
#ifdef KONAN_ANDROID
#include "CompilerConstants.hpp"
#endif
#include "std_support/String.hpp"
#include "std_support/Vector.hpp"
#include "utf8.h"
using namespace kotlin;
extern "C" {
// io/Console.kt
@@ -37,7 +41,7 @@ void Kotlin_io_Console_print(KString message) {
}
// TODO: system stdout must be aware about UTF-8.
const KChar* utf16 = CharArrayAddressOfElementAt(message, 0);
KStdString utf8;
std_support::string utf8;
utf8.reserve(message->count_);
// Replace incorrect sequences with a default codepoint (see utf8::with_replacement::default_replacement)
utf8::with_replacement::utf16to8(utf16, utf16 + message->count_, back_inserter(utf8));
@@ -77,7 +81,7 @@ OBJ_GETTER0(Kotlin_io_Console_readLine) {
}
OBJ_GETTER0(Kotlin_io_Console_readlnOrNull) {
KStdVector<char> data;
std_support::vector<char> data;
data.reserve(16);
bool isEOF = false;
bool isError = false;
@@ -16,6 +16,7 @@
#include "ScopedThread.hpp"
#include "TestSupportCompilerGenerated.hpp"
#include "TestSupport.hpp"
#include "std_support/Memory.hpp"
using namespace kotlin;
using namespace testing;
@@ -305,8 +306,8 @@ namespace {
using NativeHandlerMock = NiceMock<MockFunction<void(void)>>;
using OnUnhandledExceptionMock = NiceMock<MockFunction<void(KRef)>>;
KStdUniquePtr<NativeHandlerMock> gNativeHandlerMock = nullptr;
KStdUniquePtr<test_support::ScopedMockFunction<void(KRef), /* Strict = */ false>> gOnUnhandledExceptionMock = nullptr;
std_support::unique_ptr<NativeHandlerMock> gNativeHandlerMock = nullptr;
std_support::unique_ptr<test_support::ScopedMockFunction<void(KRef), /* Strict = */ false>> gOnUnhandledExceptionMock = nullptr;
// Google Test's death tests do not fail in case of a failed EXPECT_*/ASSERT_* check in a death statement.
// To workaround it, manually check the conditions to be asserted, log all failed conditions and then
@@ -322,7 +323,7 @@ void log(const char* message) noexcept {
}
NativeHandlerMock& setNativeTerminateHandler() noexcept {
gNativeHandlerMock = make_unique<NativeHandlerMock>();
gNativeHandlerMock = std_support::make_unique<NativeHandlerMock>();
std::set_terminate([]() {
gNativeHandlerMock->Call();
std::abort();
@@ -331,8 +332,8 @@ NativeHandlerMock& setNativeTerminateHandler() noexcept {
}
OnUnhandledExceptionMock& setKotlinTerminationHandler() noexcept {
gOnUnhandledExceptionMock =
make_unique<test_support::ScopedMockFunction<void(KRef), /* Strict = */ false>>(ScopedKotlin_runUnhandledExceptionHookMock</* Strict = */ false>());
gOnUnhandledExceptionMock = std_support::make_unique<test_support::ScopedMockFunction<void(KRef), /* Strict = */ false>>(
ScopedKotlin_runUnhandledExceptionHookMock</* Strict = */ false>());
SetKonanTerminateHandler();
return gOnUnhandledExceptionMock->get();
}
@@ -17,7 +17,11 @@
#include "ExecFormat.h"
#include "Porting.h"
#include "Types.h"
#include "std_support/CStdlib.hpp"
#include "std_support/New.hpp"
#include "std_support/Vector.hpp"
using namespace kotlin;
#if USE_ELF_SYMBOLS
@@ -58,7 +62,7 @@ struct SymRecord {
char* strtab;
};
typedef KStdVector<SymRecord> SymRecordList;
typedef std_support::vector<SymRecord> SymRecordList;
SymRecordList* symbols = nullptr;
@@ -76,7 +80,7 @@ Elf_Ehdr* findElfHeader() {
void initSymbols() {
RuntimeAssert(symbols == nullptr, "Init twice");
symbols = konanConstructInstance<SymRecordList>();
symbols = new (std_support::kalloc) SymRecordList();
Elf_Ehdr* ehdr = findElfHeader();
if (ehdr == nullptr) return;
RuntimeAssert(strncmp((const char*)ehdr->e_ident, ELFMAG, SELFMAG) == 0, "Must be an ELF");
@@ -159,10 +163,10 @@ static void* mapModuleFile(HMODULE hModule) {
DWORD bufferLength = 64;
wchar_t* buffer = nullptr;
for (;;) {
auto newBuffer = (wchar_t*)konanAllocMemory(sizeof(wchar_t) * bufferLength);
auto newBuffer = (wchar_t*)std_support::calloc(bufferLength, sizeof(wchar_t));
RuntimeAssert(newBuffer != nullptr, "Out of memory");
if (buffer != nullptr) {
konanFreeMemory(buffer);
std_support::free(buffer);
}
buffer = newBuffer;
@@ -178,7 +182,7 @@ static void* mapModuleFile(HMODULE hModule) {
}
// Invalid result.
konanFreeMemory(buffer);
std_support::free(buffer);
return nullptr;
}
@@ -191,7 +195,7 @@ static void* mapModuleFile(HMODULE hModule) {
/* dwFlagsAndAttributes = */ FILE_ATTRIBUTE_NORMAL,
/* hTemplateFile = */ nullptr
);
konanFreeMemory(buffer);
std_support::free(buffer);
if (hFile == INVALID_HANDLE_VALUE) {
// Can't open module file.
return nullptr;
@@ -323,7 +327,7 @@ extern "C" bool AddressToSymbol(const void* address, char* resultBuffer, size_t
int rv = GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
reinterpret_cast<LPCWSTR>(&AddressToSymbol), &hModule);
RuntimeAssert(rv != 0, "GetModuleHandleExW fails");
theExeSymbolTable = konanConstructInstance<SymbolTable>(hModule);
theExeSymbolTable = new (std_support::kalloc) SymbolTable(hModule);
}
return theExeSymbolTable->functionAddressToSymbol(address, resultBuffer, resultBufferSize, resultOffset);
}
@@ -19,24 +19,26 @@
#include <stdint.h>
#include <string.h>
#include "Alloc.h"
#include "KString.h"
#include "Memory.h"
#include "MemorySharedRefs.hpp"
#include "Types.h"
#include "std_support/New.hpp"
using namespace kotlin;
extern "C" {
KNativePtr Kotlin_Interop_createStablePointer(KRef any) {
KRefSharedHolder* holder = konanConstructInstance<KRefSharedHolder>();
holder->init(any);
return holder;
KRefSharedHolder* holder = new (std_support::kalloc) KRefSharedHolder();
holder->init(any);
return holder;
}
void Kotlin_Interop_disposeStablePointer(KNativePtr pointer) {
KRefSharedHolder* holder = reinterpret_cast<KRefSharedHolder*>(pointer);
holder->dispose();
konanDestructInstance(holder);
std_support::kdelete(holder);
}
OBJ_GETTER(Kotlin_Interop_derefStablePointer, KNativePtr pointer) {
@@ -11,8 +11,8 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "Types.h"
#include "Utils.hpp"
#include "std_support/List.hpp"
using namespace kotlin;
@@ -54,8 +54,8 @@ private:
};
template <typename List>
KStdList<typename List::value_type> create(std::initializer_list<int> list) {
KStdList<typename List::value_type> result;
std_support::list<typename List::value_type> create(std::initializer_list<int> list) {
std_support::list<typename List::value_type> result;
for (auto x : list) {
result.emplace_back(x);
}
@@ -24,14 +24,18 @@
#include "KString.h"
#include "Porting.h"
#include "Types.h"
#include "std_support/CStdlib.hpp"
#include "std_support/String.hpp"
#include "utf8.h"
#include "polyhash/PolyHash.h"
using namespace kotlin;
namespace {
typedef std::back_insert_iterator<KStdString> KStdStringInserter;
typedef std::back_insert_iterator<std_support::string> KStdStringInserter;
typedef KChar* utf8to16(const char*, const char*, KChar*);
typedef KStdStringInserter utf16to8(const KChar*,const KChar*, KStdStringInserter);
@@ -55,7 +59,7 @@ template<utf16to8 conversion>
OBJ_GETTER(unsafeUtf16ToUtf8Impl, KString thiz, KInt start, KInt size) {
RuntimeAssert(thiz->type_info() == theStringTypeInfo, "Must use String");
const KChar* utf16 = CharArrayAddressOfElementAt(thiz, start);
KStdString utf8;
std_support::string utf8;
utf8.reserve(size);
conversion(utf16, utf16 + size, back_inserter(utf8));
ArrayHeader* result = AllocArrayInstance(theByteArrayTypeInfo, utf8.size(), OBJ_RESULT)->array();
@@ -118,16 +122,16 @@ char* CreateCStringFromString(KConstRef kref) {
if (kref == nullptr) return nullptr;
KString kstring = kref->array();
const KChar* utf16 = CharArrayAddressOfElementAt(kstring, 0);
KStdString utf8;
std_support::string utf8;
utf8.reserve(kstring->count_);
utf8::unchecked::utf16to8(utf16, utf16 + kstring->count_, back_inserter(utf8));
char* result = reinterpret_cast<char*>(konan::calloc(1, utf8.size() + 1));
char* result = reinterpret_cast<char*>(std_support::calloc(1, utf8.size() + 1));
::memcpy(result, utf8.c_str(), utf8.size());
return result;
}
void DisposeCString(char* cstring) {
if (cstring) konan::free(cstring);
if (cstring) std_support::free(cstring);
}
// String.kt
+10 -8
View File
@@ -23,6 +23,8 @@ inline constexpr auto nullopt = std::experimental::nullopt;
#include "Format.h"
#include "KAssert.h"
#include "Porting.h"
#include "std_support/Map.hpp"
#include "std_support/String.hpp"
using namespace kotlin;
@@ -61,9 +63,9 @@ std::optional<logging::Level> ParseLevel(std::string_view levelString) noexcept
return std::nullopt;
}
KStdOrderedMap<KStdString, logging::Level> ParseTagsFilter(std::string_view tagsFilter) noexcept {
std_support::map<std_support::string, logging::Level> ParseTagsFilter(std::string_view tagsFilter) noexcept {
if (tagsFilter.empty()) return {};
KStdOrderedMap<KStdString, logging::Level> result;
std_support::map<std_support::string, logging::Level> result;
std::string_view rest = tagsFilter;
while (!rest.empty()) {
auto tag = ParseTag(rest);
@@ -83,7 +85,7 @@ KStdOrderedMap<KStdString, logging::Level> ParseTagsFilter(std::string_view tags
konan::consoleErrorf("'. No logging will be performed\n");
return {};
}
result.emplace(KStdString(tag.value->data(), tag.value->size()), *level);
result.emplace(std_support::string(tag.value->data(), tag.value->size()), *level);
}
return result;
}
@@ -108,7 +110,7 @@ public:
private:
// TODO: Make it more efficient.
KStdOrderedMap<KStdString, logging::Level> tagLevelMap_;
std_support::map<std_support::string, logging::Level> tagLevelMap_;
};
class StderrLogger : public logging::internal::Logger {
@@ -143,12 +145,12 @@ std_support::span<char> FormatTags(std_support::span<char> buffer, std_support::
} // namespace
KStdUniquePtr<logging::internal::LogFilter> logging::internal::CreateLogFilter(std::string_view tagsFilter) noexcept {
return ::make_unique<::LogFilter>(tagsFilter);
std_support::unique_ptr<logging::internal::LogFilter> logging::internal::CreateLogFilter(std::string_view tagsFilter) noexcept {
return std_support::make_unique<::LogFilter>(tagsFilter);
}
KStdUniquePtr<logging::internal::Logger> logging::internal::CreateStderrLogger() noexcept {
return ::make_unique<StderrLogger>();
std_support::unique_ptr<logging::internal::Logger> logging::internal::CreateStderrLogger() noexcept {
return std_support::make_unique<StderrLogger>();
}
std_support::span<char> logging::internal::FormatLogEntry(
@@ -22,8 +22,8 @@ using string_view = std::experimental::string_view;
#endif
#include "CompilerConstants.hpp"
#include "std_support/Memory.hpp"
#include "std_support/Span.hpp"
#include "Types.h"
namespace kotlin {
namespace logging {
@@ -45,7 +45,7 @@ public:
virtual bool Enabled(Level level, std_support::span<const char* const> tags) const noexcept = 0;
};
KStdUniquePtr<LogFilter> CreateLogFilter(std::string_view tagsFilter) noexcept;
std_support::unique_ptr<LogFilter> CreateLogFilter(std::string_view tagsFilter) noexcept;
class Logger {
public:
@@ -54,7 +54,7 @@ public:
virtual void Log(Level level, std_support::span<const char* const> tags, std::string_view message) const noexcept = 0;
};
KStdUniquePtr<Logger> CreateStderrLogger() noexcept;
std_support::unique_ptr<Logger> CreateStderrLogger() noexcept;
std_support::span<char> FormatLogEntry(
std_support::span<char> buffer,
@@ -8,6 +8,8 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "std_support/Vector.hpp"
using namespace kotlin;
using ::testing::_;
@@ -36,7 +38,7 @@ public:
}
private:
KStdUniquePtr<logging::internal::LogFilter> logFilter_;
std_support::unique_ptr<logging::internal::LogFilter> logFilter_;
};
class MockLogFilter : public logging::internal::LogFilter {
@@ -202,7 +204,7 @@ private:
};
MATCHER_P(TagsAre, tags, "") {
KStdVector<std::string_view> actualTags;
std_support::vector<std::string_view> actualTags;
for (auto tag : arg) {
actualTags.push_back(tag);
}
@@ -11,7 +11,6 @@
#include <mutex>
#include "Mutex.hpp"
#include "Types.h"
#include "Utils.hpp"
#include "std_support/List.hpp"
#include "std_support/Memory.hpp"
@@ -29,7 +28,7 @@ class MultiSourceQueue {
public:
class Producer;
// TODO: Consider switching from `KStdList` to `SingleLockList` to hide the constructor
// TODO: Consider switching from `std_support::list` to `SingleLockList` to hide the constructor
// and to not store the iterator.
class Node : private Pinned {
public:
@@ -13,7 +13,7 @@
#include "AllocatorTestSupport.hpp"
#include "ScopedThread.hpp"
#include "TestSupport.hpp"
#include "Types.h"
#include "std_support/Vector.hpp"
using namespace kotlin;
@@ -22,8 +22,8 @@ using ::testing::_;
namespace {
template <typename T, typename Mutex>
KStdVector<T> Collect(MultiSourceQueue<T, Mutex>& queue) {
KStdVector<T> result;
std_support::vector<T> Collect(MultiSourceQueue<T, Mutex>& queue) {
std_support::vector<T> result;
for (const auto& element : queue.LockForIter()) {
result.push_back(element);
}
@@ -196,8 +196,8 @@ TEST(MultiSourceQueueTest, ConcurrentPublish) {
constexpr int kThreadCount = kDefaultThreadCount;
std::atomic<bool> canStart(false);
std::atomic<int> readyCount(0);
KStdVector<ScopedThread> threads;
KStdVector<int> expected;
std_support::vector<ScopedThread> threads;
std_support::vector<int> expected;
for (int i = 0; i < kThreadCount; ++i) {
expected.push_back(i);
@@ -225,8 +225,8 @@ TEST(MultiSourceQueueTest, IterWhileConcurrentPublish) {
constexpr int kStartCount = 50;
constexpr int kThreadCount = kDefaultThreadCount;
KStdVector<int> expectedBefore;
KStdVector<int> expectedAfter;
std_support::vector<int> expectedBefore;
std_support::vector<int> expectedAfter;
IntQueue::Producer producer(queue);
for (int i = 0; i < kStartCount; ++i) {
expectedBefore.push_back(i);
@@ -238,7 +238,7 @@ TEST(MultiSourceQueueTest, IterWhileConcurrentPublish) {
std::atomic<bool> canStart(false);
std::atomic<int> readyCount(0);
std::atomic<int> startedCount(0);
KStdVector<ScopedThread> threads;
std_support::vector<ScopedThread> threads;
for (int i = 0; i < kThreadCount; ++i) {
int j = i + kStartCount;
expectedAfter.push_back(j);
@@ -253,7 +253,7 @@ TEST(MultiSourceQueueTest, IterWhileConcurrentPublish) {
});
}
KStdVector<int> actualBefore;
std_support::vector<int> actualBefore;
{
auto iter = queue.LockForIter();
while (readyCount < kThreadCount) {
@@ -282,7 +282,7 @@ TEST(MultiSourceQueueTest, ConcurrentPublishAndApplyDeletions) {
std::atomic<bool> canStart(false);
std::atomic<int> readyCount(0);
std::atomic<int> startedCount(0);
KStdVector<ScopedThread> threads;
std_support::vector<ScopedThread> threads;
for (int i = 0; i < kThreadCount; ++i) {
threads.emplace_back([&queue, i, &canStart, &readyCount, &startedCount]() {
IntQueue::Producer producer(queue);
@@ -28,6 +28,9 @@
#include "Porting.h"
#include "Natives.h"
#include "Types.h"
#include "std_support/CStdlib.hpp"
using namespace kotlin;
extern "C" {
@@ -87,7 +90,7 @@ void* Kotlin_interop_malloc(KLong size, KInt align) {
RuntimeAssert(align > 0, "Unsupported alignment");
RuntimeAssert((align & (align - 1)) == 0, "Alignment must be power of two");
void* result = konan::calloc_aligned(1, size, align);
void* result = std_support::aligned_calloc(align, 1, size);
if ((reinterpret_cast<uintptr_t>(result) & (align - 1)) != 0) {
// Unaligned!
RuntimeAssert(false, "unsupported alignment");
@@ -97,7 +100,7 @@ void* Kotlin_interop_malloc(KLong size, KInt align) {
}
void Kotlin_interop_free(void* ptr) {
konan::free(ptr);
std_support::free(ptr);
}
void Kotlin_system_exitProcess(KInt status) {
@@ -43,6 +43,22 @@
#import "Runtime.h"
#import "Mutex.hpp"
#import "Exceptions.h"
#include "std_support/CStdlib.hpp"
#include "std_support/Map.hpp"
#include "std_support/String.hpp"
#include "std_support/UnorderedSet.hpp"
#include "std_support/Vector.hpp"
using namespace kotlin;
namespace {
template <typename T>
inline T* konanAllocArray(size_t length) {
return reinterpret_cast<T*>(std_support::calloc(length, sizeof(T)));
}
}
struct ObjCToKotlinMethodAdapter {
const char* selector;
@@ -653,7 +669,7 @@ static id Kotlin_ObjCExport_refToRetainedObjC_slowpath(ObjHeader* obj) {
return convertToRetained(obj);
}
static void buildITable(TypeInfo* result, const KStdOrderedMap<ClassId, KStdVector<VTableElement>>& interfaceVTables) {
static void buildITable(TypeInfo* result, const std_support::map<ClassId, std_support::vector<VTableElement>>& interfaceVTables) {
// Check if can use fast optimistic version - check if the size of the itable could be 2^k and <= 32.
bool useFastITable;
int itableSize = 1;
@@ -687,7 +703,7 @@ static void buildITable(TypeInfo* result, const KStdOrderedMap<ClassId, KStdVect
}
} else {
// Otherwise: conservative version.
// The table will be sorted since we're using KStdOrderedMap.
// The table will be sorted since we're using std_support::map.
int index = 0;
for (auto& pair : interfaceVTables) {
auto interfaceId = pair.first;
@@ -712,15 +728,15 @@ static void buildITable(TypeInfo* result, const KStdOrderedMap<ClassId, KStdVect
static const TypeInfo* createTypeInfo(
const TypeInfo* superType,
const KStdVector<const TypeInfo*>& superInterfaces,
const KStdVector<VTableElement>& vtable,
const KStdOrderedMap<ClassId, KStdVector<VTableElement>>& interfaceVTables,
const std_support::vector<const TypeInfo*>& superInterfaces,
const std_support::vector<VTableElement>& vtable,
const std_support::map<ClassId, std_support::vector<VTableElement>>& interfaceVTables,
const InterfaceTableRecord* superItable,
int superItableSize,
bool itableEqualsSuper,
const TypeInfo* fieldsInfo
) {
TypeInfo* result = (TypeInfo*)konanAllocMemory(sizeof(TypeInfo) + vtable.size() * sizeof(void*));
TypeInfo* result = (TypeInfo*)std_support::calloc(1, sizeof(TypeInfo) + vtable.size() * sizeof(void*));
result->typeInfo_ = result;
result->flags_ = TF_OBJC_DYNAMIC;
@@ -741,10 +757,10 @@ static const TypeInfo* createTypeInfo(
result->classId_ = superType->classId_;
KStdVector<const TypeInfo*> implementedInterfaces(
std_support::vector<const TypeInfo*> implementedInterfaces(
superType->implementedInterfaces_, superType->implementedInterfaces_ + superType->implementedInterfacesCount_
);
KStdUnorderedSet<const TypeInfo*> usedInterfaces(implementedInterfaces.begin(), implementedInterfaces.end());
std_support::unordered_set<const TypeInfo*> usedInterfaces(implementedInterfaces.begin(), implementedInterfaces.end());
for (const TypeInfo* interface : superInterfaces) {
if (usedInterfaces.insert(interface).second) {
@@ -770,14 +786,14 @@ static const TypeInfo* createTypeInfo(
result->packageName_ = nullptr;
result->relativeName_ = nullptr; // TODO: add some info.
result->writableInfo_ = (WritableTypeInfo*)konanAllocMemory(sizeof(WritableTypeInfo));
result->writableInfo_ = (WritableTypeInfo*)std_support::calloc(1, sizeof(WritableTypeInfo));
for (size_t i = 0; i < vtable.size(); ++i) result->vtable()[i] = vtable[i];
return result;
}
static void addDefinedSelectors(Class clazz, KStdUnorderedSet<SEL>& result) {
static void addDefinedSelectors(Class clazz, std_support::unordered_set<SEL>& result) {
unsigned int objcMethodCount;
Method* objcMethods = class_copyMethodList(clazz, &objcMethodCount);
@@ -788,10 +804,10 @@ static void addDefinedSelectors(Class clazz, KStdUnorderedSet<SEL>& result) {
if (objcMethods != nullptr) free(objcMethods);
}
static KStdVector<const TypeInfo*> getProtocolsAsInterfaces(Class clazz) {
KStdVector<const TypeInfo*> result;
KStdUnorderedSet<Protocol*> handledProtocols;
KStdVector<Protocol*> protocolsToHandle;
static std_support::vector<const TypeInfo*> getProtocolsAsInterfaces(Class clazz) {
std_support::vector<const TypeInfo*> result;
std_support::unordered_set<Protocol*> handledProtocols;
std_support::vector<Protocol*> protocolsToHandle;
{
unsigned int protocolCount;
@@ -847,7 +863,7 @@ static void throwIfCantBeOverridden(Class clazz, const KotlinToObjCMethodAdapter
}
static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, const TypeInfo* fieldsInfo) {
KStdUnorderedSet<SEL> definedSelectors;
std_support::unordered_set<SEL> definedSelectors;
addDefinedSelectors(clazz, definedSelectors);
const ObjCTypeAdapter* superTypeAdapter = getTypeAdapter(superType);
@@ -870,7 +886,7 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, co
if (superVtable == nullptr) superVtable = superType->vtable();
KStdVector<const void*> vtable(
std_support::vector<const void*> vtable(
superVtable,
superVtable + superVtableSize
);
@@ -879,7 +895,7 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, co
superITable = superType->interfaceTable_;
superITableSize = superType->interfaceTableSize_;
}
KStdOrderedMap<ClassId, KStdVector<VTableElement>> interfaceVTables;
std_support::map<ClassId, std_support::vector<VTableElement>> interfaceVTables;
if (superITable != nullptr) {
int actualItableSize = superITableSize >= 0 ? superITableSize + 1 : -superITableSize;
for (int i = 0; i < actualItableSize; ++i) {
@@ -887,16 +903,16 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, co
auto interfaceId = record.id;
if (interfaceId == kInvalidInterfaceId) continue;
int vtableSize = record.vtableSize;
KStdVector<VTableElement> interfaceVTable(vtableSize);
std_support::vector<VTableElement> interfaceVTable(vtableSize);
for (int j = 0; j < vtableSize; ++j)
interfaceVTable[j] = record.vtable[j];
interfaceVTables.emplace(interfaceId, std::move(interfaceVTable));
}
}
KStdVector<const TypeInfo*> addedInterfaces = getProtocolsAsInterfaces(clazz);
std_support::vector<const TypeInfo*> addedInterfaces = getProtocolsAsInterfaces(clazz);
KStdVector<const TypeInfo*> supers(
std_support::vector<const TypeInfo*> supers(
superType->implementedInterfaces_,
superType->implementedInterfaces_ + superType->implementedInterfacesCount_
);
@@ -921,7 +937,7 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, co
auto interfaceVTablesIt = interfaceVTables.find(interfaceId);
if (interfaceVTablesIt == interfaceVTables.end()) {
itableEqualsSuper = false;
interfaceVTables.emplace(interfaceId, KStdVector<VTableElement>(itableSize));
interfaceVTables.emplace(interfaceId, std_support::vector<VTableElement>(itableSize));
} else {
auto const& interfaceVTable = interfaceVTablesIt->second;
RuntimeAssert(interfaceVTable.size() == static_cast<size_t>(itableSize), "");
@@ -1036,7 +1052,7 @@ static Class createClass(const TypeInfo* typeInfo, Class superClass) {
RuntimeAssert(typeInfo->superType_ != nullptr, "");
int classIndex = (anonymousClassNextId++);
KStdString className = Kotlin_ObjCInterop_getUniquePrefix();
std_support::string className = Kotlin_ObjCInterop_getUniquePrefix();
className += "_kobjcc";
className += std::to_string(classIndex);
@@ -1056,7 +1072,7 @@ static Class createClass(const TypeInfo* typeInfo, Class superClass) {
}
}
KStdUnorderedSet<const TypeInfo*> superImplementedInterfaces(
std_support::unordered_set<const TypeInfo*> superImplementedInterfaces(
typeInfo->superType_->implementedInterfaces_,
typeInfo->superType_->implementedInterfaces_ + typeInfo->superType_->implementedInterfacesCount_
);
@@ -36,6 +36,9 @@
#include "StackTrace.hpp"
#include "Types.h"
#include "Mutex.hpp"
#include "std_support/String.hpp"
using namespace kotlin;
// Replaced in ObjCExportCodeGenerator.
__attribute__((weak)) const char* Kotlin_ObjCInterop_uniquePrefix = nullptr;
@@ -267,7 +270,7 @@ NO_EXTERNAL_CALLS_CHECK static Class allocateClass(const KotlinObjCClassInfo* in
fprintf(stderr, "Class %s has multiple implementations. Which one will be used is undefined.\n", info->name);
}
KStdString className = Kotlin_ObjCInterop_getUniquePrefix();
std_support::string className = Kotlin_ObjCInterop_getUniquePrefix();
if (info->name != nullptr) {
className += info->name;
@@ -11,6 +11,7 @@
#include "TypeInfo.h"
#include "Types.h"
#include "Utils.hpp"
#include "std_support/Vector.hpp"
namespace kotlin {
namespace test_support {
@@ -26,7 +27,7 @@ private:
virtual ~Builder() = default;
int32_t instanceSize_ = 0;
KStdVector<int32_t> objOffsets_;
std_support::vector<int32_t> objOffsets_;
int32_t flags_ = 0;
const TypeInfo* superType_ = nullptr;
};
@@ -88,7 +89,7 @@ public:
private:
TypeInfo typeInfo_{};
KStdVector<int32_t> objOffsets_;
std_support::vector<int32_t> objOffsets_;
};
template <typename Payload>
@@ -10,6 +10,7 @@
#include "Natives.h"
#include "TestSupport.hpp"
#include "std_support/Vector.hpp"
using namespace kotlin;
@@ -68,8 +69,8 @@ using ObjectTestCases = testing::Types<RegularObjectTestCase, IrregularObjectTes
TYPED_TEST_SUITE(ObjectTestSupportObjectTest, ObjectTestCases, ObjectTestCaseNames);
template <typename Payload>
KStdVector<ObjHeader**> Collect(test_support::Object<Payload>& object) {
KStdVector<ObjHeader**> result;
std_support::vector<ObjHeader**> Collect(test_support::Object<Payload>& object) {
std_support::vector<ObjHeader**> result;
for (auto& field : object.fields()) {
result.push_back(&field);
}
@@ -307,8 +308,8 @@ using ArrayTestCases = testing::Types<
TYPED_TEST_SUITE(ObjectTestSupportArrayTest, ArrayTestCases, ArrayTestCaseNames);
template <typename Payload, size_t ElementCount>
KStdVector<Payload*> Collect(test_support::internal::Array<Payload, ElementCount>& array) {
KStdVector<Payload*> result;
std_support::vector<Payload*> Collect(test_support::internal::Array<Payload, ElementCount>& array) {
std_support::vector<Payload*> result;
for (auto& element : array.elements()) {
result.push_back(&element);
}
@@ -329,7 +330,7 @@ TYPED_TEST(ObjectTestSupportArrayTest, Local) {
EXPECT_THAT(array.arrayHeader()->count_, size);
EXPECT_THAT(array.elements().size(), size);
KStdVector<Payload*> expected;
std_support::vector<Payload*> expected;
for (size_t i = 0; i < size; ++i) {
auto* element = AddressOfElementAt<Payload>(array.arrayHeader(), i);
EXPECT_THAT(&array.elements()[i], element);
@@ -360,7 +361,7 @@ TYPED_TEST(ObjectTestSupportArrayTest, Heap) {
EXPECT_THAT(array.arrayHeader()->count_, size);
EXPECT_THAT(array.elements().size(), size);
KStdVector<Payload*> expected;
std_support::vector<Payload*> expected;
for (size_t i = 0; i < size; ++i) {
auto* element = AddressOfElementAt<Payload>(array.arrayHeader(), i);
EXPECT_THAT(&array.elements()[i], element);
@@ -14,7 +14,6 @@
* limitations under the License.
*/
#include "Alloc.h"
#include "Atomic.h"
#include "Cleaner.h"
#include "CompilerConstants.hpp"
@@ -27,11 +26,14 @@
#include "RuntimePrivate.hpp"
#include "Worker.h"
#include "KString.h"
#include "std_support/New.hpp"
#ifndef KONAN_NO_THREADS
#include <thread>
#endif
using namespace kotlin;
using kotlin::internal::FILE_NOT_INITIALIZED;
using kotlin::internal::FILE_BEING_INITIALIZED;
using kotlin::internal::FILE_INITIALIZED;
@@ -100,7 +102,7 @@ volatile GlobalRuntimeStatus globalRuntimeStatus = kGlobalRuntimeUninitialized;
RuntimeState* initRuntime() {
SetKonanTerminateHandler();
RuntimeState* result = konanConstructInstance<RuntimeState>();
RuntimeState* result = new (std_support::kalloc) RuntimeState();
if (!result) return kInvalidRuntime;
RuntimeCheck(!isValidRuntime(), "No active runtimes allowed");
::runtimeState = result;
@@ -188,7 +190,7 @@ void deinitRuntime(RuntimeState* state, bool destroyRuntime) {
// Do not use ThreadStateGuard because memoryState will be destroyed during DeinitMemory.
kotlin::SwitchThreadState(state->memoryState, kotlin::ThreadState::kNative);
DeinitMemory(state->memoryState, destroyRuntime);
konanDestructInstance(state);
std_support::kdelete(state);
WorkerDestroyThreadDataIfNeeded(workerId);
::runtimeState = kInvalidRuntime;
}
@@ -12,8 +12,8 @@
#include <string_view>
#include <thread>
#include "Types.h"
#include "Utils.hpp"
#include "std_support/String.hpp"
namespace kotlin {
namespace internal {
@@ -46,7 +46,7 @@ public:
private:
friend class ScopedThread;
std::optional<KStdString> name_;
std::optional<std_support::string> name_;
};
ScopedThread() noexcept = default;
@@ -13,7 +13,6 @@
#include <type_traits>
#include "Mutex.hpp"
#include "Types.h"
#include "Utils.hpp"
#include "std_support/Memory.hpp"
@@ -14,7 +14,8 @@
#include "AllocatorTestSupport.hpp"
#include "ScopedThread.hpp"
#include "TestSupport.hpp"
#include "Types.h"
#include "std_support/Deque.hpp"
#include "std_support/Vector.hpp"
using namespace kotlin;
@@ -51,7 +52,7 @@ TEST(SingleLockListTest, EmplaceAndIter) {
list.Emplace(kSecond);
list.Emplace(kThird);
KStdVector<int> actual;
std_support::vector<int> actual;
for (int element : list.LockForIter()) {
actual.push_back(element);
}
@@ -69,7 +70,7 @@ TEST(SingleLockListTest, EmplaceEraseAndIter) {
list.Emplace(kThird);
list.Erase(secondNode);
KStdVector<int> actual;
std_support::vector<int> actual;
for (int element : list.LockForIter()) {
actual.push_back(element);
}
@@ -80,7 +81,7 @@ TEST(SingleLockListTest, EmplaceEraseAndIter) {
TEST(SingleLockListTest, IterEmpty) {
IntList list;
KStdVector<int> actual;
std_support::vector<int> actual;
for (int element : list.LockForIter()) {
actual.push_back(element);
}
@@ -101,7 +102,7 @@ TEST(SingleLockListTest, EraseToEmptyEmplaceAndIter) {
list.Emplace(kThird);
list.Emplace(kFourth);
KStdVector<int> actual;
std_support::vector<int> actual;
for (int element : list.LockForIter()) {
actual.push_back(element);
}
@@ -114,8 +115,8 @@ TEST(SingleLockListTest, ConcurrentEmplace) {
constexpr int kThreadCount = kDefaultThreadCount;
std::atomic<bool> canStart(false);
std::atomic<int> readyCount(0);
KStdVector<ScopedThread> threads;
KStdVector<int> expected;
std_support::vector<ScopedThread> threads;
std_support::vector<int> expected;
for (int i = 0; i < kThreadCount; ++i) {
expected.push_back(i);
threads.emplace_back([i, &list, &canStart, &readyCount]() {
@@ -131,7 +132,7 @@ TEST(SingleLockListTest, ConcurrentEmplace) {
canStart = true;
threads.clear();
KStdVector<int> actual;
std_support::vector<int> actual;
for (int element : list.LockForIter()) {
actual.push_back(element);
}
@@ -142,14 +143,14 @@ TEST(SingleLockListTest, ConcurrentEmplace) {
TEST(SingleLockListTest, ConcurrentErase) {
IntList list;
constexpr int kThreadCount = kDefaultThreadCount;
KStdVector<IntList::Node*> items;
std_support::vector<IntList::Node*> items;
for (int i = 0; i < kThreadCount; ++i) {
items.push_back(list.Emplace(i));
}
std::atomic<bool> canStart(false);
std::atomic<int> readyCount(0);
KStdVector<ScopedThread> threads;
std_support::vector<ScopedThread> threads;
for (auto* item : items) {
threads.emplace_back([item, &list, &canStart, &readyCount]() {
++readyCount;
@@ -164,7 +165,7 @@ TEST(SingleLockListTest, ConcurrentErase) {
canStart = true;
threads.clear();
KStdVector<int> actual;
std_support::vector<int> actual;
for (int element : list.LockForIter()) {
actual.push_back(element);
}
@@ -177,8 +178,8 @@ TEST(SingleLockListTest, IterWhileConcurrentEmplace) {
constexpr int kStartCount = 50;
constexpr int kThreadCount = kDefaultThreadCount;
KStdDeque<int> expectedBefore;
KStdVector<int> expectedAfter;
std_support::deque<int> expectedBefore;
std_support::vector<int> expectedAfter;
for (int i = 0; i < kStartCount; ++i) {
expectedBefore.push_front(i);
expectedAfter.push_back(i);
@@ -187,7 +188,7 @@ TEST(SingleLockListTest, IterWhileConcurrentEmplace) {
std::atomic<bool> canStart(false);
std::atomic<int> startedCount(0);
KStdVector<ScopedThread> threads;
std_support::vector<ScopedThread> threads;
for (int i = 0; i < kThreadCount; ++i) {
int j = i + kStartCount;
expectedAfter.push_back(j);
@@ -199,7 +200,7 @@ TEST(SingleLockListTest, IterWhileConcurrentEmplace) {
});
}
KStdVector<int> actualBefore;
std_support::vector<int> actualBefore;
{
auto iter = list.LockForIter();
canStart = true;
@@ -215,7 +216,7 @@ TEST(SingleLockListTest, IterWhileConcurrentEmplace) {
EXPECT_THAT(actualBefore, testing::ElementsAreArray(expectedBefore));
KStdVector<int> actualAfter;
std_support::vector<int> actualAfter;
for (int element : list.LockForIter()) {
actualAfter.push_back(element);
}
@@ -227,8 +228,8 @@ TEST(SingleLockListTest, IterWhileConcurrentErase) {
IntList list;
constexpr int kThreadCount = kDefaultThreadCount;
KStdDeque<int> expectedBefore;
KStdVector<IntList::Node*> items;
std_support::deque<int> expectedBefore;
std_support::vector<IntList::Node*> items;
for (int i = 0; i < kThreadCount; ++i) {
expectedBefore.push_front(i);
items.push_back(list.Emplace(i));
@@ -236,7 +237,7 @@ TEST(SingleLockListTest, IterWhileConcurrentErase) {
std::atomic<bool> canStart(false);
std::atomic<int> startedCount(0);
KStdVector<ScopedThread> threads;
std_support::vector<ScopedThread> threads;
for (auto* item : items) {
threads.emplace_back([item, &list, &canStart, &startedCount]() {
while (!canStart) {
@@ -246,7 +247,7 @@ TEST(SingleLockListTest, IterWhileConcurrentErase) {
});
}
KStdVector<int> actualBefore;
std_support::vector<int> actualBefore;
{
auto iter = list.LockForIter();
canStart = true;
@@ -262,7 +263,7 @@ TEST(SingleLockListTest, IterWhileConcurrentErase) {
EXPECT_THAT(actualBefore, testing::ElementsAreArray(expectedBefore));
KStdVector<int> actualAfter;
std_support::vector<int> actualAfter;
for (int element : list.LockForIter()) {
actualAfter.push_back(element);
}
@@ -274,10 +275,10 @@ TEST(SingleLockListTest, LockAndEmplace) {
SingleLockList<int, std::recursive_mutex> list;
constexpr int kThreadCount = kDefaultThreadCount;
KStdVector<ScopedThread> threads;
KStdVector<int> actualLocked;
KStdVector<int> actualUnlocked;
KStdVector<int> expectedUnlocked;
std_support::vector<ScopedThread> threads;
std_support::vector<int> actualLocked;
std_support::vector<int> actualUnlocked;
std_support::vector<int> expectedUnlocked;
for (int i = 0; i < kThreadCount; i++) {
expectedUnlocked.push_back(i);
}
@@ -313,11 +314,11 @@ TEST(SingleLockListTest, LockAndErase) {
SingleLockList<int, std::recursive_mutex> list;
constexpr int kThreadCount = kDefaultThreadCount;
KStdVector<SingleLockList<int, std::recursive_mutex>::Node*> items;
KStdVector<int> expectedLocked;
KStdVector<ScopedThread> threads;
KStdVector<int> actualLocked;
KStdVector<int> actualUnlocked;
std_support::vector<SingleLockList<int, std::recursive_mutex>::Node*> items;
std_support::vector<int> expectedLocked;
std_support::vector<ScopedThread> threads;
std_support::vector<int> actualLocked;
std_support::vector<int> actualUnlocked;
std::atomic<int> startedCount(0);
for (int i = 0; i < kThreadCount; i++) {
@@ -376,7 +377,7 @@ TEST(SingleLockListTest, PinnedType) {
list.Erase(itemNode);
KStdVector<PinnedType*> actualAfter;
std_support::vector<PinnedType*> actualAfter;
for (auto& element : list.LockForIter()) {
actualAfter.push_back(&element);
}
@@ -12,8 +12,8 @@
#include <shared_mutex>
#include "ScopedThread.hpp"
#include "Types.h"
#include "Utils.hpp"
#include "std_support/Deque.hpp"
namespace kotlin {
@@ -101,7 +101,7 @@ private:
std::condition_variable workCV_;
std::mutex workMutex_;
KStdDeque<std::packaged_task<void()>> queue_;
std_support::deque<std::packaged_task<void()>> queue_;
bool shutdownRequested_ = false;
ScopedThread thread_;
@@ -10,6 +10,8 @@
#include "KAssert.h"
#include "TestSupport.hpp"
#include "std_support/Memory.hpp"
#include "std_support/Vector.hpp"
using namespace kotlin;
@@ -60,7 +62,7 @@ TEST(SingleThreadExecutorTest, ContextThreadBound) {
createdContext = &context;
createdThread = std::this_thread::get_id();
});
auto executor = ::make_unique<SingleThreadExecutor<PinnedContext>>();
auto executor = std_support::make_unique<SingleThreadExecutor<PinnedContext>>();
// Make sure context is created.
executor->context();
testing::Mock::VerifyAndClearExpectations(&mocks.ctorMock);
@@ -127,7 +129,7 @@ TEST(SingleThreadExecutorTest, execute) {
TEST(SingleThreadExecutorTest, DropExecutorWithTasks) {
struct Context {};
auto executor = make_unique<SingleThreadExecutor<Context>>();
auto executor = std_support::make_unique<SingleThreadExecutor<Context>>();
std::mutex taskMutex;
testing::StrictMock<testing::MockFunction<void()>> task;
@@ -141,7 +143,7 @@ TEST(SingleThreadExecutorTest, DropExecutorWithTasks) {
auto future = executor->execute(task.AsStdFunction());
while (!taskStarted) {}
KStdVector<std::pair<std::future<void>, bool>> newTasks;
std_support::vector<std::pair<std::future<void>, bool>> newTasks;
constexpr size_t tasksCount = 100;
for (size_t i = 0; i < tasksCount; ++i) {
newTasks.push_back(std::make_pair(executor->execute([&newTasks, i] { newTasks[i].second = true; }), false));
@@ -165,14 +167,14 @@ TEST(SingleThreadExecutorTest, DropExecutorWithTasks) {
TEST(SingleThreadExecutorTest, ExecuteFromManyThreads) {
struct Context {
KStdVector<int> result;
std_support::vector<int> result;
};
SingleThreadExecutor<Context> executor;
std::atomic_bool canStart = false;
KStdVector<int> expected;
KStdVector<ScopedThread> threads;
std_support::vector<int> expected;
std_support::vector<ScopedThread> threads;
for (int i = 0; i < kDefaultThreadCount; ++i) {
expected.push_back(i);
threads.emplace_back([&, i] {
@@ -90,7 +90,7 @@ int getSourceInfo(void* symbol, SourceInfo *result, int result_len) {
// TODO: this implementation is just a hack, e.g. the result is inexact;
// however it is better to have an inexact stacktrace than not to have any.
NO_INLINE KStdVector<void*> kotlin::internal::GetCurrentStackTrace(size_t skipFrames) noexcept {
NO_INLINE std_support::vector<void*> kotlin::internal::GetCurrentStackTrace(size_t skipFrames) noexcept {
NativeOrUnregisteredThreadGuard guard(true);
#if KONAN_NO_BACKTRACE
return {};
@@ -104,7 +104,7 @@ NO_INLINE KStdVector<void*> kotlin::internal::GetCurrentStackTrace(size_t skipFr
const size_t kSkipFrames = 1 + skipFrames;
#endif
KStdVector<void*> result;
std_support::vector<void*> result;
#if USE_GCC_UNWIND
size_t depth = 0;
_Unwind_Backtrace(depthCountCallback, static_cast<void*>(&depth));
@@ -238,15 +238,15 @@ KNativePtr adjustAddressForSourceInfo(KNativePtr address) {
KNativePtr adjustAddressForSourceInfo(KNativePtr address) { return address; }
#endif
KStdVector<KStdString> kotlin::GetStackTraceStrings(std_support::span<void* const> stackTrace) noexcept {
std_support::vector<std_support::string> kotlin::GetStackTraceStrings(std_support::span<void* const> stackTrace) noexcept {
NativeOrUnregisteredThreadGuard guard(true);
#if KONAN_NO_BACKTRACE
KStdVector<KStdString> strings;
std_support::vector<std_support::string> strings;
strings.push_back("<UNIMPLEMENTED>");
return strings;
#else
size_t size = stackTrace.size();
KStdVector<KStdString> strings;
std_support::vector<std_support::string> strings;
strings.reserve(size);
if (size > 0) {
SourceInfo buffer[10]; // outside of the loop to avoid calling constructors and destructors each time
@@ -8,13 +8,14 @@
#include "std_support/Span.hpp"
#include "Memory.h"
#include "Types.h"
#include "std_support/String.hpp"
#include "std_support/Vector.hpp"
namespace kotlin {
namespace internal {
NO_INLINE KStdVector<void*> GetCurrentStackTrace(size_t skipFrames) noexcept;
NO_INLINE std_support::vector<void*> GetCurrentStackTrace(size_t skipFrames) noexcept;
NO_INLINE size_t GetCurrentStackTrace(size_t skipFrames, std_support::span<void*> buffer) noexcept;
enum class StackTraceCapacityKind {
@@ -181,19 +182,18 @@ public:
struct TestSupport : private Pinned {
static StackTrace constructFrom(std::initializer_list<void*> values) {
KStdVector<void*> traceElements(values);
std_support::vector<void*> traceElements(values);
return StackTrace(std::move(traceElements));
}
};
private:
explicit StackTrace(KStdVector<void*>&& buffer) noexcept : buffer_(buffer) {}
explicit StackTrace(std_support::vector<void*>&& buffer) noexcept : buffer_(buffer) {}
KStdVector<void*> buffer_;
std_support::vector<void*> buffer_;
};
KStdVector<KStdString> GetStackTraceStrings(std_support::span<void* const> stackTrace) noexcept;
std_support::vector<std_support::string> GetStackTraceStrings(std_support::span<void* const> stackTrace) noexcept;
// It's not always safe to extract SourceInfo during unhandled exception termination.
void DisallowSourceInfo();
@@ -214,4 +214,4 @@ struct std::hash<kotlin::StackTrace<Capacity>> {
}
};
#endif // RUNTIME_STACK_TRACE_H
#endif // RUNTIME_STACK_TRACE_H
@@ -13,6 +13,7 @@
#include "Common.h"
#include "Porting.h"
#include "TestSupport.hpp"
#include "std_support/UnorderedSet.hpp"
#include <iostream>
@@ -187,7 +188,7 @@ TEST(StackTraceTest, StackAllocatedDeepTraceWithEnoughCapacity) {
TEST(StackTraceTest, Iteration) {
auto stackTrace = GetStackTrace2();
KStdVector<void*> actualAddresses;
std_support::vector<void*> actualAddresses;
for (auto addr : stackTrace) {
actualAddresses.push_back(addr);
}
@@ -203,7 +204,7 @@ TEST(StackTraceTest, Iteration) {
TEST(StackTraceTest, StackAllocatedIteration) {
auto stackTrace = GetStackTrace2<2>();
KStdVector<void*> actualAddresses;
std_support::vector<void*> actualAddresses;
for (auto addr : stackTrace) {
actualAddresses.push_back(addr);
}
@@ -219,7 +220,7 @@ TEST(StackTraceTest, StackAllocatedIteration) {
TEST(StackTraceTest, IndexedAccess) {
auto stackTrace = GetStackTrace2();
KStdVector<void*> actualAddresses;
std_support::vector<void*> actualAddresses;
for (size_t i = 0; i < stackTrace.size(); i++) {
actualAddresses.push_back(stackTrace[i]);
}
@@ -233,7 +234,7 @@ TEST(StackTraceTest, IndexedAccess) {
TEST(StackTraceTest, StackAllocatedIndexedAccess) {
auto stackTrace = GetStackTrace2<2>();
KStdVector<void*> actualAddresses;
std_support::vector<void*> actualAddresses;
for (size_t i = 0; i < stackTrace.size(); i++) {
actualAddresses.push_back(stackTrace[i]);
}
@@ -334,7 +335,7 @@ TEST(StackTraceTest, StackAllocatedEqualsAndHash) {
TEST(StackTraceTest, StoreInHashSet) {
constexpr size_t capacity = 10;
KStdUnorderedSet<StackTrace<capacity>> set;
std_support::unordered_set<StackTrace<capacity>> set;
StackTrace<capacity> empty;
StackTrace<capacity> trace1 = GetStackTrace1<capacity>();
StackTrace<capacity> trace2 = GetStackTrace2<capacity>();
@@ -359,7 +360,7 @@ TEST(StackTraceTest, StoreInHashSet) {
}
TEST(StackTraceTest, StackAllocatedStoreInHashSet) {
KStdUnorderedSet<StackTrace<>> set;
std_support::unordered_set<StackTrace<>> set;
StackTrace<> empty;
StackTrace<> trace1 = GetStackTrace1();
StackTrace<> trace2 = GetStackTrace2();
@@ -11,6 +11,7 @@
#include "Types.h"
#include "Utils.hpp"
#include "std_support/Memory.hpp"
namespace kotlin {
namespace test_support {
@@ -34,7 +35,7 @@ public:
explicit ScopedMockFunction(testing::MockFunction<F>** globalMockLocation) : globalMockLocation_(globalMockLocation) {
RuntimeCheck(globalMockLocation != nullptr, "ScopedMockFunction needs non-null global mock location");
RuntimeCheck(*globalMockLocation == nullptr, "ScopedMockFunction needs null global mock");
mock_ = make_unique<Mock>();
mock_ = std_support::make_unique<Mock>();
*globalMockLocation_ = mock_.get();
}
@@ -69,7 +70,7 @@ public:
private:
// Can be null if moved-out of.
testing::MockFunction<F>** globalMockLocation_;
KStdUniquePtr<Mock> mock_;
std_support::unique_ptr<Mock> mock_;
};
template<bool Strict = true>
@@ -93,4 +94,4 @@ ScopedMockFunction<void(KRef), Strict> ScopedKotlin_runUnhandledExceptionHookMoc
}
} // namespace test_support
} // namespace kotlin
} // namespace kotlin
@@ -19,19 +19,9 @@
#include <stdlib.h>
#include "Alloc.h"
#include "Common.h"
#include "Memory.h"
#include "TypeInfo.h"
#include "std_support/Deque.hpp"
#include "std_support/List.hpp"
#include "std_support/Map.hpp"
#include "std_support/Memory.hpp"
#include "std_support/Set.hpp"
#include "std_support/String.hpp"
#include "std_support/UnorderedMap.hpp"
#include "std_support/UnorderedSet.hpp"
#include "std_support/Vector.hpp"
// Note that almost all types are signed.
typedef bool KBoolean;
@@ -55,26 +45,6 @@ typedef ObjHeader* KRef;
typedef const ObjHeader* KConstRef;
typedef const ArrayHeader* KString;
// TODO: Remove these typedefs. Use std_support directly everywhere.
using KStdString = kotlin::std_support::string;
template <typename Value>
using KStdDeque = kotlin::std_support::deque<Value>;
template <typename Key, typename Value>
using KStdUnorderedMap = kotlin::std_support::unordered_map<Key, Value>;
template <typename Value>
using KStdUnorderedSet = kotlin::std_support::unordered_set<Value>;
template <typename Value, typename Compare = std::less<Value>>
using KStdOrderedMultiset = kotlin::std_support::multiset<Value, Compare>;
template <typename Key, typename Value>
using KStdOrderedMap = kotlin::std_support::map<Key, Value>;
template <typename Value>
using KStdVector = kotlin::std_support::vector<Value>;
template <typename Value>
using KStdList = kotlin::std_support::list<Value>;
template <typename Value>
using KStdUniquePtr = kotlin::std_support::unique_ptr<Value>;
using kotlin::std_support::make_unique;
#ifdef __cplusplus
extern "C" {
#endif
+17 -13
View File
@@ -27,7 +27,6 @@
#include "PthreadUtils.h"
#endif
#include "Alloc.h"
#include "Exceptions.h"
#include "KAssert.h"
#include "Memory.h"
@@ -35,6 +34,11 @@
#include "Runtime.h"
#include "Types.h"
#include "Worker.h"
#include "std_support/Deque.hpp"
#include "std_support/New.hpp"
#include "std_support/Set.hpp"
#include "std_support/UnorderedMap.hpp"
#include "std_support/Vector.hpp"
using namespace kotlin;
@@ -133,7 +137,7 @@ struct JobCompare {
// Using multiset instead of regular set, because we compare the jobs only by `whenExecute`.
// So if `whenExecute` of two different jobs is the same, the jobs are considered equivalent,
// and set would simply drop one of them.
typedef KStdOrderedMultiset<Job, JobCompare> DelayedJobSet;
typedef std_support::multiset<Job, JobCompare> DelayedJobSet;
} // namespace
@@ -200,7 +204,7 @@ class Worker {
KInt id_;
WorkerKind kind_;
KStdDeque<Job> queue_;
std_support::deque<Job> queue_;
DelayedJobSet delayed_;
// Stable pointer with worker's name.
KNativePtr name_;
@@ -359,7 +363,7 @@ class State {
Worker* worker = nullptr;
{
Locker locker(&lock_);
worker = konanConstructInstance<Worker>(nextWorkerId(), exceptionHandling, customName, kind);
worker = new (std_support::kalloc) Worker(nextWorkerId(), exceptionHandling, customName, kind);
if (worker == nullptr) return nullptr;
workers_[worker->id()] = worker;
}
@@ -392,7 +396,7 @@ class State {
}
}
GC_UnregisterWorker(worker);
konanDestructInstance(worker);
std_support::kdelete(worker);
}
Future* addJobToWorkerUnlocked(
@@ -405,7 +409,7 @@ class State {
if (it == workers_.end()) return nullptr;
worker = it->second;
future = konanConstructInstance<Future>(nextFutureId());
future = new (std_support::kalloc) Future(nextFutureId());
futures_[future->id()] = future;
Job job;
@@ -507,7 +511,7 @@ class State {
auto it = futures_.find(id);
if (it != futures_.end()) {
futures_.erase(it);
konanDestructInstance(future);
std_support::kdelete(future);
}
}
@@ -581,7 +585,7 @@ class State {
template <typename F>
void waitNativeWorkersTerminationUnlocked(bool checkLeaks, F waitForWorker) {
KStdVector<std::pair<KInt, pthread_t>> workersToWait;
std_support::vector<std::pair<KInt, pthread_t>> workersToWait;
{
Locker locker(&lock_);
@@ -628,9 +632,9 @@ class State {
private:
pthread_mutex_t lock_;
pthread_cond_t cond_;
KStdUnorderedMap<KInt, Future*> futures_;
KStdUnorderedMap<KInt, Worker*> workers_;
KStdUnorderedMap<KInt, pthread_t> terminating_native_workers_;
std_support::unordered_map<KInt, Future*> futures_;
std_support::unordered_map<KInt, Worker*> workers_;
std_support::unordered_map<KInt, pthread_t> terminating_native_workers_;
KInt currentWorkerId_;
KInt currentFutureId_;
KInt currentVersion_;
@@ -643,11 +647,11 @@ State* theState() {
return state;
}
State* result = konanConstructInstance<State>();
State* result = new (std_support::kalloc) State();
State* old = __sync_val_compare_and_swap(&state, nullptr, result);
if (old != nullptr) {
konanDestructInstance(result);
std_support::kdelete(result);
// Someone else inited this data.
return old;
}
@@ -5,9 +5,11 @@
#include "WorkerBoundReference.h"
#include "Alloc.h"
#include "Memory.h"
#include "MemorySharedRefs.hpp"
#include "std_support/New.hpp"
using namespace kotlin;
namespace {
@@ -27,7 +29,7 @@ RUNTIME_NOTHROW void DisposeWorkerBoundReference(KRef thiz) {
// Can be null if WorkerBoundReference wasn't frozen.
if (auto* holder = asWorkerBoundReference(thiz)->holder) {
holder->dispose();
konanDestructInstance(holder);
std_support::kdelete(holder);
}
}
@@ -41,9 +43,9 @@ RUNTIME_NOTHROW void WorkerBoundReferenceFreezeHook(KRef thiz) {
extern "C" {
KNativePtr Kotlin_WorkerBoundReference_create(KRef value) {
auto* holder = konanConstructInstance<KRefSharedHolder>();
holder->init(value);
return holder;
auto* holder = new (std_support::kalloc) KRefSharedHolder();
holder->init(value);
return holder;
}
OBJ_GETTER(Kotlin_WorkerBoundReference_deref, KNativePtr holder) {
@@ -28,6 +28,10 @@
#include "../KotlinMath.h"
#include "../ReturnSlot.h"
#include "../DoubleConversions.h"
#include "../std_support/CStdlib.hpp"
#include "../std_support/String.hpp"
using namespace kotlin;
#if defined(LINUX) || defined(FREEBSD) || defined(ZOS) || defined(MACOSX) || defined(AIX)
#define USE_LL
@@ -177,8 +181,8 @@ static const KDouble tens[] = {
}
#define ERROR_OCCURED(x) (HIGH_I32_FROM_VAR(x) < 0)
#define allocateU64(x, n) if (!((x) = (U_64*) konan::calloc(1, (n) * sizeof(U_64)))) goto OutOfMemory;
#define release(r) if ((r)) konan::free((r));
#define allocateU64(x, n) if (!((x) = (U_64*) std_support::calloc(1, (n) * sizeof(U_64)))) goto OutOfMemory;
#define release(r) if ((r)) std_support::free((r));
/*NB the Number converter methods are synchronized so it is possible to
*have global data for use by bigIntDigitGenerator */
@@ -654,7 +658,7 @@ OutOfMemory:
KDouble Kotlin_native_FloatingPointParser_parseDoubleImpl (KString s, KInt e)
{
const KChar* utf16 = CharArrayAddressOfElementAt(s, 0);
KStdString utf8;
std_support::string utf8;
utf8.reserve(s->count_);
TRY_CATCH(utf8::utf16to8(utf16, utf16 + s->count_, back_inserter(utf8)),
utf8::unchecked::utf16to8(utf16, utf16 + s->count_, back_inserter(utf8)),
@@ -25,6 +25,10 @@
#include "../Natives.h"
#include "../Porting.h"
#include "../utf8.h"
#include "../std_support/CStdlib.hpp"
#include "../std_support/String.hpp"
using namespace kotlin;
#if defined(LINUX) || defined(FREEBSD) || defined(MACOSX) || defined(ZOS) || defined(AIX)
#define USE_LL
@@ -117,8 +121,8 @@ static const U_32 tens[] = {
} \
}
#define allocateU64(x, n) if (!((x) = (U_64*) konan::calloc(1, (n) * sizeof(U_64)))) goto OutOfMemory;
#define release(r) if ((r)) konan::free((r));
#define allocateU64(x, n) if (!((x) = (U_64*) std_support::calloc(1, (n) * sizeof(U_64)))) goto OutOfMemory;
#define release(r) if ((r)) std_support::free((r));
KFloat createFloat(const char *s, KInt e) {
/* assumes s is a null terminated string with at least one
@@ -542,7 +546,7 @@ extern "C" KFloat
Kotlin_native_FloatingPointParser_parseFloatImpl(KString s, KInt e)
{
const KChar* utf16 = CharArrayAddressOfElementAt(s, 0);
KStdString utf8;
std_support::string utf8;
utf8.reserve(s->count_);
TRY_CATCH(utf8::utf16to8(utf16, utf16 + s->count_, back_inserter(utf8)),
utf8::unchecked::utf16to8(utf16, utf16 + s->count_, back_inserter(utf8)),
@@ -15,14 +15,6 @@ void* operator new(std::size_t count, kotlin::std_support::kalloc_t) noexcept {
return std_support::calloc(1, count);
}
void* operator new[](std::size_t count, kotlin::std_support::kalloc_t) noexcept {
return std_support::calloc(1, count);
}
void operator delete(void* ptr, kotlin::std_support::kalloc_t) noexcept {
std_support::free(ptr);
}
void operator delete[](void* ptr, kotlin::std_support::kalloc_t) noexcept {
std_support::free(ptr);
}
@@ -18,9 +18,7 @@ inline constexpr kalloc_t kalloc = kotlin::std_support::kalloc_t{};
// (also requires removing `-fno-aligned-allocation` compiler flag).
void* operator new(std::size_t count, kotlin::std_support::kalloc_t) noexcept;
void* operator new[](std::size_t count, kotlin::std_support::kalloc_t) noexcept;
void operator delete(void* ptr, kotlin::std_support::kalloc_t) noexcept;
void operator delete[](void* ptr, kotlin::std_support::kalloc_t) noexcept;
namespace kotlin::std_support {
@@ -40,16 +40,6 @@ TEST(NewTest, NewDelete) {
std_support::kdelete(ptr);
}
TEST(NewTest, NewDeleteArray) {
Class* ptr = new (std_support::kalloc) Class[13];
EXPECT_THAT(ptr[3].x(), 17);
std_support::kdelete(ptr);
}
TEST(NewTest, NewThrows) {
EXPECT_THROW(new (std_support::kalloc) ClassThrows(42), int);
}
TEST(NewTest, NewThrowsArray) {
EXPECT_THROW(new (std_support::kalloc) ClassThrows[13], int);
}
@@ -13,6 +13,7 @@
#include "ThreadData.hpp"
#include "ThreadRegistry.hpp"
#include "ExecFormat.h"
#include "std_support/UnorderedSet.hpp"
using namespace kotlin;
@@ -314,7 +315,7 @@ public:
~KnownFunctionChecker() = delete;
private:
KStdUnorderedSet<const void*> known_functions_;
std_support::unordered_set<const void*> known_functions_;
std::string_view good_names_copy_[sizeof(Kotlin_callsCheckerGoodFunctionNames) / sizeof(Kotlin_callsCheckerGoodFunctionNames[0])];
};
@@ -12,6 +12,7 @@
#include "TestSupport.hpp"
#include "ThreadData.hpp"
#include "Types.h"
#include "std_support/Vector.hpp"
using namespace kotlin;
@@ -19,11 +20,11 @@ namespace {
class ExceptionObjHolderTest : public ::testing::Test {
public:
static KStdVector<ObjHeader*> Collect(mm::ThreadData& threadData) {
static std_support::vector<ObjHeader*> Collect(mm::ThreadData& threadData) {
auto& stableRefs = mm::StableRefRegistry::Instance();
stableRefs.ProcessThread(&threadData);
stableRefs.ProcessDeletions();
KStdVector<ObjHeader*> result;
std_support::vector<ObjHeader*> result;
for (const auto& obj : stableRefs.LockForIter()) {
result.push_back(obj);
}
@@ -10,7 +10,6 @@
#include <cstddef>
#include <cstdint>
#include "Alloc.h"
#include "Memory.h"
#include "TypeInfo.h"
#include "Utils.hpp"
@@ -11,6 +11,8 @@
#include "Natives.h"
#include "ObjectTraversal.hpp"
#include "Types.h"
#include "std_support/UnorderedSet.hpp"
#include "std_support/Vector.hpp"
using namespace kotlin;
@@ -29,10 +31,10 @@ bool mm::IsFrozen(const ObjHeader* object) noexcept {
ObjHeader* mm::FreezeSubgraph(ObjHeader* root) noexcept {
if (IsFrozen(root)) return nullptr;
KStdVector<ObjHeader*> objects;
KStdVector<ObjHeader*> stack;
std_support::vector<ObjHeader*> objects;
std_support::vector<ObjHeader*> stack;
// TODO: This may be a suboptimal container for the job.
KStdUnorderedSet<ObjHeader*> visited;
std_support::unordered_set<ObjHeader*> visited;
stack.push_back(root);
while (!stack.empty()) {
ObjHeader* object = stack.back();
@@ -40,7 +40,7 @@ public:
void ProcessThread(mm::ThreadData* threadData) noexcept;
// Lock registry for safe iteration.
// TODO: Iteration over `globals_` will be slow, because it's `KStdList` collected at different times from
// TODO: Iteration over `globals_` will be slow, because it's `std_support::list` collected at different times from
// different threads, and so the nodes are all over the memory. Use metrics to understand how
// much of a problem is it.
Iterable LockForIter() noexcept { return globals_.LockForIter(); }
@@ -15,6 +15,7 @@
#include "TestSupport.hpp"
#include "ThreadData.hpp"
#include "Types.h"
#include "std_support/Vector.hpp"
using namespace kotlin;
@@ -200,10 +201,10 @@ TEST_F(InitSingletonTest, InitSingletonConcurrent) {
constexpr size_t kThreadCount = kDefaultThreadCount;
std::atomic<bool> canStart(false);
std::atomic<size_t> readyCount(0);
KStdVector<ScopedThread> threads;
std_support::vector<ScopedThread> threads;
ObjHeader* location = nullptr;
KStdVector<ObjHeader*> stackLocations(kThreadCount, nullptr);
KStdVector<ObjHeader*> actual(kThreadCount, nullptr);
std_support::vector<ObjHeader*> stackLocations(kThreadCount, nullptr);
std_support::vector<ObjHeader*> actual(kThreadCount, nullptr);
for (size_t i = 0; i < kThreadCount; ++i) {
threads.emplace_back([this, i, &location, &stackLocations, &actual, &readyCount, &canStart]() {
@@ -234,10 +235,10 @@ TEST_F(InitSingletonTest, InitSingletonConcurrentFailing) {
constexpr size_t kThreadCount = kDefaultThreadCount;
std::atomic<bool> canStart(false);
std::atomic<size_t> readyCount(0);
KStdVector<ScopedThread> threads;
std_support::vector<ScopedThread> threads;
constexpr int kException = 42;
ObjHeader* location = nullptr;
KStdVector<ObjHeader*> stackLocations(kThreadCount, nullptr);
std_support::vector<ObjHeader*> stackLocations(kThreadCount, nullptr);
for (size_t i = 0; i < kThreadCount; ++i) {
threads.emplace_back([this, i, &location, &stackLocations, &readyCount, &canStart]() {
@@ -12,7 +12,6 @@
#include <type_traits>
#include "Alignment.hpp"
#include "Alloc.h"
#include "FinalizerHooks.hpp"
#include "Memory.h"
#include "Mutex.hpp"
@@ -18,6 +18,8 @@
#include "ScopedThread.hpp"
#include "TestSupport.hpp"
#include "Types.h"
#include "std_support/CStdlib.hpp"
#include "std_support/Vector.hpp"
using namespace kotlin;
@@ -39,8 +41,8 @@ template <typename Storage>
using Consumer = typename Storage::Consumer;
template <size_t DataAlignment>
KStdVector<void*> Collect(ObjectFactoryStorage<DataAlignment>& storage) {
KStdVector<void*> result;
std_support::vector<void*> Collect(ObjectFactoryStorage<DataAlignment>& storage) {
std_support::vector<void*> result;
for (auto& node : storage.LockForIter()) {
result.push_back(node.Data());
}
@@ -48,8 +50,8 @@ KStdVector<void*> Collect(ObjectFactoryStorage<DataAlignment>& storage) {
}
template <typename T, size_t DataAlignment>
KStdVector<T> Collect(ObjectFactoryStorage<DataAlignment>& storage) {
KStdVector<T> result;
std_support::vector<T> Collect(ObjectFactoryStorage<DataAlignment>& storage) {
std_support::vector<T> result;
for (auto& node : storage.LockForIter()) {
result.push_back(*static_cast<T*>(node.Data()));
}
@@ -57,8 +59,8 @@ KStdVector<T> Collect(ObjectFactoryStorage<DataAlignment>& storage) {
}
template <typename T, size_t DataAlignment>
KStdVector<T> Collect(Consumer<ObjectFactoryStorage<DataAlignment>>& consumer) {
KStdVector<T> result;
std_support::vector<T> Collect(Consumer<ObjectFactoryStorage<DataAlignment>>& consumer) {
std_support::vector<T> result;
for (auto& node : consumer) {
result.push_back(*static_cast<T*>(node.Data()));
}
@@ -630,8 +632,8 @@ TEST(ObjectFactoryStorageTest, ConcurrentPublish) {
constexpr int kThreadCount = kDefaultThreadCount;
std::atomic<bool> canStart(false);
std::atomic<int> readyCount(0);
KStdVector<ScopedThread> threads;
KStdVector<int> expected;
std_support::vector<ScopedThread> threads;
std_support::vector<int> expected;
for (int i = 0; i < kThreadCount; ++i) {
expected.push_back(i);
@@ -661,8 +663,8 @@ TEST(ObjectFactoryStorageTest, IterWhileConcurrentPublish) {
constexpr int kStartCount = 50;
constexpr int kThreadCount = kDefaultThreadCount;
KStdVector<int> expectedBefore;
KStdVector<int> expectedAfter;
std_support::vector<int> expectedBefore;
std_support::vector<int> expectedAfter;
Producer<ObjectFactoryStorageRegular> producer(storage, SimpleAllocator());
for (int i = 0; i < kStartCount; ++i) {
expectedBefore.push_back(i);
@@ -674,7 +676,7 @@ TEST(ObjectFactoryStorageTest, IterWhileConcurrentPublish) {
std::atomic<bool> canStart(false);
std::atomic<int> readyCount(0);
std::atomic<int> startedCount(0);
KStdVector<ScopedThread> threads;
std_support::vector<ScopedThread> threads;
for (int i = 0; i < kThreadCount; ++i) {
int j = i + kStartCount;
expectedAfter.push_back(j);
@@ -689,7 +691,7 @@ TEST(ObjectFactoryStorageTest, IterWhileConcurrentPublish) {
});
}
KStdVector<int> actualBefore;
std_support::vector<int> actualBefore;
{
auto iter = storage.LockForIter();
while (readyCount < kThreadCount) {
@@ -719,7 +721,7 @@ TEST(ObjectFactoryStorageTest, EraseWhileConcurrentPublish) {
constexpr int kStartCount = 50;
constexpr int kThreadCount = kDefaultThreadCount;
KStdVector<int> expectedAfter;
std_support::vector<int> expectedAfter;
Producer<ObjectFactoryStorageRegular> producer(storage, SimpleAllocator());
for (int i = 0; i < kStartCount; ++i) {
if (i % 2 == 0) {
@@ -732,7 +734,7 @@ TEST(ObjectFactoryStorageTest, EraseWhileConcurrentPublish) {
std::atomic<bool> canStart(false);
std::atomic<int> readyCount(0);
std::atomic<int> startedCount(0);
KStdVector<ScopedThread> threads;
std_support::vector<ScopedThread> threads;
for (int i = 0; i < kThreadCount; ++i) {
int j = i + kStartCount;
expectedAfter.push_back(j);
@@ -782,9 +784,9 @@ public:
MOCK_METHOD(void*, Alloc, (size_t, size_t));
MOCK_METHOD(void, Free, (void*));
void* DefaultAlloc(size_t size, size_t alignment) { return konanAllocAlignedMemory(size, alignment); }
void* DefaultAlloc(size_t size, size_t alignment) { return std_support::aligned_calloc(alignment, 1, size); }
void DefaultFree(void* instance) { konanFreeMemory(instance); }
void DefaultFree(void* instance) { std_support::free(instance); }
};
class GlobalMockAllocator {
@@ -1056,7 +1058,7 @@ TEST(ObjectFactoryTest, RunFinalizers) {
ObjectFactory::ThreadQueue threadQueue(objectFactory, GlobalMockAllocator());
ObjectFactory::FinalizerQueue finalizerQueue;
KStdVector<ObjHeader*> objects;
std_support::vector<ObjHeader*> objects;
EXPECT_CALL(allocator, Alloc(_, _)).Times(10);
for (int i = 0; i < 10; ++i) {
objects.push_back(threadQueue.CreateObject(objectType.typeInfo()));
@@ -1089,9 +1091,9 @@ TEST(ObjectFactoryTest, ConcurrentPublish) {
constexpr int kThreadCount = kDefaultThreadCount;
std::atomic<bool> canStart(false);
std::atomic<int> readyCount(0);
KStdVector<ScopedThread> threads;
std_support::vector<ScopedThread> threads;
std::mutex expectedMutex;
KStdVector<ObjHeader*> expected;
std_support::vector<ObjHeader*> expected;
EXPECT_CALL(allocator, Alloc(_, _)).Times(kThreadCount);
for (int i = 0; i < kThreadCount; ++i) {
@@ -1116,7 +1118,7 @@ TEST(ObjectFactoryTest, ConcurrentPublish) {
threads.clear();
auto iter = objectFactory.LockForIter();
KStdVector<ObjHeader*> actual;
std_support::vector<ObjHeader*> actual;
for (auto it = iter.begin(); it != iter.end(); ++it) {
actual.push_back(it->GetObjHeader());
}
@@ -9,6 +9,8 @@
#include "gtest/gtest.h"
#include "ShadowStack.hpp"
#include "std_support/Memory.hpp"
#include "std_support/Vector.hpp"
using namespace kotlin;
@@ -21,7 +23,7 @@ class StackEntry : private Pinned {
public:
static_assert(LocalsCount > 0, "Must have at least 1 object on stack");
explicit StackEntry(mm::ShadowStack& shadowStack) : shadowStack_(shadowStack), value_(make_unique<ObjHeader>()) {
explicit StackEntry(mm::ShadowStack& shadowStack) : shadowStack_(shadowStack), value_(std_support::make_unique<ObjHeader>()) {
// Fill `locals_` with some values.
for (size_t i = 0; i < LocalsCount; ++i) {
(*this)[i] = value_.get() + i;
@@ -36,7 +38,7 @@ public:
private:
mm::ShadowStack& shadowStack_;
KStdUniquePtr<ObjHeader> value_;
std_support::unique_ptr<ObjHeader> value_;
// The following is what the compiler creates on the stack.
static inline constexpr int kFrameOverlayCount = sizeof(FrameOverlay) / sizeof(ObjHeader**);
@@ -59,7 +61,7 @@ TEST(ThreadRootSetTest, Basic) {
mm::ThreadRootSet iter(stack, tls);
KStdVector<mm::ThreadRootSet::Value> actual;
std_support::vector<mm::ThreadRootSet::Value> actual;
for (auto object : iter) {
actual.push_back(object);
}
@@ -79,7 +81,7 @@ TEST(ThreadRootSetTest, Empty) {
mm::ThreadRootSet iter(stack, tls);
KStdVector<mm::ThreadRootSet::Value> actual;
std_support::vector<mm::ThreadRootSet::Value> actual;
for (auto object : iter) {
actual.push_back(object);
}
@@ -109,7 +111,7 @@ TEST(GlobalRootSetTest, Basic) {
mm::GlobalRootSet iter(globals, stableRefs);
KStdVector<mm::GlobalRootSet::Value> actual;
std_support::vector<mm::GlobalRootSet::Value> actual;
for (auto object : iter) {
actual.push_back(object);
}
@@ -128,7 +130,7 @@ TEST(GlobalRootSetTest, Empty) {
mm::GlobalRootSet iter(globals, stableRefs);
KStdVector<mm::GlobalRootSet::Value> actual;
std_support::vector<mm::GlobalRootSet::Value> actual;
for (auto object : iter) {
actual.push_back(object);
}
@@ -11,6 +11,8 @@
#include "Memory.h"
#include "Types.h"
#include "Utils.hpp"
#include "std_support/Memory.hpp"
#include "std_support/Vector.hpp"
using namespace kotlin;
@@ -21,7 +23,7 @@ class StackEntry : private Pinned {
public:
static_assert(ParametersCount + LocalsCount > 0, "Must have at least 1 object on stack");
explicit StackEntry(mm::ShadowStack& shadowStack) : shadowStack_(shadowStack), value_(make_unique<ObjHeader>()) {
explicit StackEntry(mm::ShadowStack& shadowStack) : shadowStack_(shadowStack), value_(std_support::make_unique<ObjHeader>()) {
// Fill `locals_` with some values.
for (size_t i = 0; i < LocalsCount; ++i) {
(*this)[i] = value_.get() + i;
@@ -36,7 +38,7 @@ public:
private:
mm::ShadowStack& shadowStack_;
KStdUniquePtr<ObjHeader> value_;
std_support::unique_ptr<ObjHeader> value_;
// The following is what the compiler creates on the stack.
static inline constexpr int kFrameOverlayCount = sizeof(FrameOverlay) / sizeof(ObjHeader**);
@@ -44,8 +46,8 @@ private:
std::array<ObjHeader*, kTotalCount> data_;
};
KStdVector<ObjHeader*> Collect(mm::ShadowStack& shadowStack) {
KStdVector<ObjHeader*> result;
std_support::vector<ObjHeader*> Collect(mm::ShadowStack& shadowStack) {
std_support::vector<ObjHeader*> result;
for (ObjHeader* local : shadowStack) {
result.push_back(local);
}
@@ -45,7 +45,7 @@ public:
void ProcessDeletions() noexcept;
// Lock registry for safe iteration.
// TODO: Iteration over `stableRefs_` will be slow, because it's `KStdList` collected at different times from
// TODO: Iteration over `stableRefs_` will be slow, because it's `std_support::list` collected at different times from
// different threads, and so the nodes are all over the memory. Use metrics to understand how
// much of a problem is it.
Iterable LockForIter() noexcept { return stableRefs_.LockForIter(); }
@@ -17,9 +17,9 @@
#include "ShadowStack.hpp"
#include "StableRefRegistry.hpp"
#include "ThreadLocalStorage.hpp"
#include "Types.h"
#include "Utils.hpp"
#include "ThreadSuspension.hpp"
#include "std_support/Vector.hpp"
struct ObjHeader;
@@ -56,7 +56,7 @@ public:
ShadowStack& shadowStack() noexcept { return shadowStack_; }
KStdVector<std::pair<ObjHeader**, ObjHeader*>>& initializingSingletons() noexcept { return initializingSingletons_; }
std_support::vector<std::pair<ObjHeader**, ObjHeader*>>& initializingSingletons() noexcept { return initializingSingletons_; }
gc::GC::ThreadData& gc() noexcept { return gc_; }
@@ -85,7 +85,7 @@ private:
ExtraObjectDataFactory::ThreadQueue extraObjectDataThreadQueue_;
ShadowStack shadowStack_;
gc::GC::ThreadData gc_;
KStdVector<std::pair<ObjHeader**, ObjHeader*>> initializingSingletons_;
std_support::vector<std::pair<ObjHeader**, ObjHeader*>> initializingSingletons_;
ThreadSuspensionData suspensionData_;
};
@@ -13,6 +13,8 @@
#include "Memory.h"
#include "Types.h"
#include "Utils.hpp"
#include "std_support/UnorderedMap.hpp"
#include "std_support/Vector.hpp"
namespace kotlin {
namespace mm {
@@ -23,7 +25,7 @@ public:
class Iterator {
public:
explicit Iterator(KStdVector<ObjHeader*>::iterator iterator) : iterator_(iterator) {}
explicit Iterator(std_support::vector<ObjHeader*>::iterator iterator) : iterator_(iterator) {}
ObjHeader** operator*() noexcept { return &*iterator_; }
@@ -36,7 +38,7 @@ public:
bool operator!=(const Iterator& rhs) const noexcept { return iterator_ != rhs.iterator_; }
private:
KStdVector<ObjHeader*>::iterator iterator_;
std_support::vector<ObjHeader*>::iterator iterator_;
};
// Add TLS record. Can only be called before `Commit`.
@@ -65,9 +67,9 @@ private:
ObjHeader** Lookup(Entry entry, int index) noexcept;
KStdVector<ObjHeader*> storage_;
// TODO: `KStdUnorderedMap` is probably the wrong container here.
KStdUnorderedMap<Key, Entry> map_;
std_support::vector<ObjHeader*> storage_;
// TODO: `std_support::unordered_map` is probably the wrong container here.
std_support::unordered_map<Key, Entry> map_;
State state_ = State::kBuilding;
int size_ = 0; // Only used in `State::kBuilding`
std::pair<Key, Entry> lastKeyAndEntry_;
@@ -56,12 +56,12 @@ TEST(ThreadLocalStorageTest, Iterate) {
tls.AddRecord(&key2, 2);
tls.Commit();
KStdVector<ObjHeader**> expected;
std_support::vector<ObjHeader**> expected;
expected.push_back(tls.Lookup(&key1, 0));
expected.push_back(tls.Lookup(&key2, 0));
expected.push_back(tls.Lookup(&key2, 1));
KStdVector<ObjHeader**> actual;
std_support::vector<ObjHeader**> actual;
for (auto item : tls) {
actual.push_back(item);
}
@@ -80,12 +80,12 @@ TEST(ThreadLocalStorageTest, AddRecordEmpty) {
tls.AddRecord(&key3, 2);
tls.Commit();
KStdVector<ObjHeader**> expected;
std_support::vector<ObjHeader**> expected;
expected.push_back(tls.Lookup(&key1, 0));
expected.push_back(tls.Lookup(&key3, 0));
expected.push_back(tls.Lookup(&key3, 1));
KStdVector<ObjHeader**> actual;
std_support::vector<ObjHeader**> actual;
for (auto item : tls) {
actual.push_back(item);
}
@@ -101,10 +101,10 @@ TEST(ThreadLocalStorageTest, AddRecordSameSize) {
tls.AddRecord(&key1, 1);
tls.Commit();
KStdVector<ObjHeader**> expected;
std_support::vector<ObjHeader**> expected;
expected.push_back(tls.Lookup(&key1, 0));
KStdVector<ObjHeader**> actual;
std_support::vector<ObjHeader**> actual;
for (auto item : tls) {
actual.push_back(item);
}
@@ -117,7 +117,7 @@ TEST(ThreadLocalStorageTest, NoRecords) {
tls.Commit();
KStdVector<ObjHeader**> actual;
std_support::vector<ObjHeader**> actual;
for (auto item : tls) {
actual.push_back(item);
}
@@ -132,7 +132,7 @@ TEST(ThreadLocalStorageTest, ClearEmpty) {
tls.Clear();
KStdVector<ObjHeader**> actual;
std_support::vector<ObjHeader**> actual;
for (auto item : tls) {
actual.push_back(item);
}
@@ -149,7 +149,7 @@ TEST(ThreadLocalStorageTest, ClearNonEmpty) {
tls.Clear();
KStdVector<ObjHeader**> actual;
std_support::vector<ObjHeader**> actual;
for (auto item : tls) {
actual.push_back(item);
}
@@ -9,6 +9,7 @@
#include "ScopedThread.hpp"
#include "ThreadSuspension.hpp"
#include "ThreadState.hpp"
#include "std_support/Vector.hpp"
#include <gtest/gtest.h>
#include <gmock/gmock.h>
@@ -31,8 +32,8 @@ constexpr size_t kDefaultIterations = 10000;
constexpr size_t kDefaultReportingStep = 1000;
#endif // #ifdef KONAN_WINDOWS
KStdVector<mm::ThreadData*> collectThreadData() {
KStdVector<mm::ThreadData*> result;
std_support::vector<mm::ThreadData*> collectThreadData() {
std_support::vector<mm::ThreadData*> result;
auto iter = mm::ThreadRegistry::Instance().LockForIter();
for (auto& thread : iter) {
result.push_back(&thread);
@@ -40,15 +41,15 @@ KStdVector<mm::ThreadData*> collectThreadData() {
return result;
}
template<typename T, typename F>
KStdVector<T> collectFromThreadData(F extractFunction) {
KStdVector<T> result;
template <typename T, typename F>
std_support::vector<T> collectFromThreadData(F extractFunction) {
std_support::vector<T> result;
auto threadData = collectThreadData();
std::transform(threadData.begin(), threadData.end(), std::back_inserter(result), extractFunction);
return result;
}
KStdVector<bool> collectSuspended() {
std_support::vector<bool> collectSuspended() {
return collectFromThreadData<bool>(
[](mm::ThreadData* threadData) { return threadData->suspensionData().suspended(); });
}
@@ -82,7 +83,7 @@ public:
static constexpr size_t kThreadCount = kDefaultThreadCount;
static constexpr size_t kIterations = kDefaultIterations;
KStdVector<ScopedThread> threads;
std_support::vector<ScopedThread> threads;
std::array<std::atomic<bool>, kThreadCount> ready{false};
std::atomic<bool> canStart{false};
std::atomic<bool> shouldStop{false};