blob: d8250b126b7400457e568139f2c3c2b487ac4373 [file]
/*
* Copyright 2010-2021 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.
*/
#include "RootSet.hpp"
#include "KAssert.h"
#include "GlobalData.hpp"
#include "ThreadData.hpp"
using namespace kotlin;
mm::ThreadRootSet::Iterator::Iterator(begin_t, ThreadRootSet& owner) noexcept :
owner_(owner), phase_(Phase::kStack), stackIterator_(owner_.stack_.begin()) {
Init();
}
mm::ThreadRootSet::Iterator::Iterator(end_t, ThreadRootSet& owner) noexcept : owner_(owner), phase_(Phase::kDone) {}
mm::ThreadRootSet::Value mm::ThreadRootSet::Iterator::operator*() noexcept {
switch (phase_) {
case Phase::kStack:
return {*stackIterator_, Source::kStack};
case Phase::kTLS:
return {**tlsIterator_, Source::kTLS};
case Phase::kDone:
RuntimeFail("Cannot dereference");
}
}
mm::ThreadRootSet::Iterator& mm::ThreadRootSet::Iterator::operator++() noexcept {
switch (phase_) {
case Phase::kStack:
++stackIterator_;
Init();
return *this;
case Phase::kTLS:
++tlsIterator_;
Init();
return *this;
case Phase::kDone:
return *this;
}
}
bool mm::ThreadRootSet::Iterator::operator==(const Iterator& rhs) const noexcept {
if (phase_ != rhs.phase_) {
return false;
}
switch (phase_) {
case Phase::kDone:
return true;
case Phase::kStack:
return stackIterator_ == rhs.stackIterator_;
case Phase::kTLS:
return tlsIterator_ == rhs.tlsIterator_;
}
}
void mm::ThreadRootSet::Iterator::Init() noexcept {
while (phase_ != Phase::kDone) {
switch (phase_) {
case Phase::kStack:
if (stackIterator_ != owner_.stack_.end()) return;
phase_ = Phase::kTLS;
tlsIterator_ = owner_.tls_.begin();
break;
case Phase::kTLS:
if (tlsIterator_ != owner_.tls_.end()) return;
phase_ = Phase::kDone;
break;
case Phase::kDone:
RuntimeFail("Impossible");
}
}
}
mm::GlobalRootSet::Iterator::Iterator(begin_t, GlobalRootSet& owner) noexcept :
owner_(owner), phase_(Phase::kGlobals), globalsIterator_(owner_.globalsIterable_.begin()) {
Init();
}
mm::GlobalRootSet::Iterator::Iterator(end_t, GlobalRootSet& owner) noexcept : owner_(owner), phase_(Phase::kDone) {}
mm::GlobalRootSet::Value mm::GlobalRootSet::Iterator::operator*() noexcept {
switch (phase_) {
case Phase::kGlobals:
return {**globalsIterator_, Source::kGlobal};
case Phase::kStableRefs:
return {*specialRefsIterator_, Source::kStableRef};
case Phase::kDone:
RuntimeFail("Cannot dereference");
}
}
mm::GlobalRootSet::Iterator& mm::GlobalRootSet::Iterator::operator++() noexcept {
switch (phase_) {
case Phase::kGlobals:
++globalsIterator_;
Init();
return *this;
case Phase::kStableRefs:
++specialRefsIterator_;
Init();
return *this;
case Phase::kDone:
return *this;
}
}
bool mm::GlobalRootSet::Iterator::operator==(const Iterator& rhs) const noexcept {
if (phase_ != rhs.phase_) {
return false;
}
switch (phase_) {
case Phase::kDone:
return true;
case Phase::kGlobals:
return globalsIterator_ == rhs.globalsIterator_;
case Phase::kStableRefs:
return specialRefsIterator_ == rhs.specialRefsIterator_;
}
}
void mm::GlobalRootSet::Iterator::Init() noexcept {
while (phase_ != Phase::kDone) {
switch (phase_) {
case Phase::kGlobals:
if (globalsIterator_ != owner_.globalsIterable_.end()) return;
phase_ = Phase::kStableRefs;
specialRefsIterator_ = owner_.specialRefsIterable_.begin();
break;
case Phase::kStableRefs:
if (specialRefsIterator_ != owner_.specialRefsIterable_.end()) return;
phase_ = Phase::kDone;
break;
case Phase::kDone:
RuntimeFail("Impossible");
}
}
}
mm::ThreadRootSet::ThreadRootSet(ThreadData& threadData) noexcept : ThreadRootSet(threadData.shadowStack(), threadData.tls()) {}
mm::GlobalRootSet::GlobalRootSet() noexcept :
GlobalRootSet(mm::GlobalData::Instance().globalsRegistry(), mm::GlobalData::Instance().specialRefRegistry()) {}