Extract FreezeHooks and make them testable (#4654)
This commit is contained in:
committed by
Vasily Levchenko
parent
e2280ce855
commit
d84c83d7da
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 "FreezeHooks.hpp"
|
||||
|
||||
#include "Memory.h"
|
||||
#include "Types.h"
|
||||
#include "WorkerBoundReference.h"
|
||||
|
||||
using namespace kotlin;
|
||||
|
||||
namespace {
|
||||
|
||||
void (*g_hookOverrideForTesting)(ObjHeader*) = nullptr;
|
||||
|
||||
NO_INLINE void RunFreezeHooksImpl(ObjHeader* object, const TypeInfo* type) noexcept {
|
||||
if (g_hookOverrideForTesting != nullptr) {
|
||||
g_hookOverrideForTesting(object);
|
||||
return;
|
||||
}
|
||||
// TODO: Consider some global registration.
|
||||
if (type == theWorkerBoundReferenceTypeInfo) {
|
||||
WorkerBoundReferenceFreezeHook(object);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void kotlin::RunFreezeHooks(ObjHeader* object) noexcept {
|
||||
auto* type = object->type_info();
|
||||
if ((type->flags_ & TF_HAS_FREEZE_HOOK) == 0) {
|
||||
return;
|
||||
}
|
||||
// This is a cold path.
|
||||
RunFreezeHooksImpl(object, type);
|
||||
}
|
||||
|
||||
void kotlin::SetFreezeHookForTesting(void (*hook)(ObjHeader*)) noexcept {
|
||||
g_hookOverrideForTesting = hook;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RUNTIME_MM_FREEZE_HOOKS_H
|
||||
#define RUNTIME_MM_FREEZE_HOOKS_H
|
||||
|
||||
struct ObjHeader;
|
||||
struct TypeInfo;
|
||||
|
||||
namespace kotlin {
|
||||
|
||||
// These hooks are only allowed to modify `object` subgraph.
|
||||
void RunFreezeHooks(ObjHeader* object) noexcept;
|
||||
|
||||
void SetFreezeHookForTesting(void (*hook)(ObjHeader*)) noexcept;
|
||||
|
||||
} // namespace kotlin
|
||||
|
||||
#endif // RUNTIME_MM_FREEZE_HOOKS_H
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 "FreezeHooks.hpp"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
#include "FreezeHooksTestSupport.hpp"
|
||||
#include "Memory.h"
|
||||
|
||||
using namespace kotlin;
|
||||
|
||||
using ::testing::_;
|
||||
|
||||
namespace {
|
||||
|
||||
class FreezeHooksTest : public testing::Test {
|
||||
public:
|
||||
testing::MockFunction<void(ObjHeader*)>& freezeHook() { return freezeHooks_.freezeHook(); }
|
||||
|
||||
private:
|
||||
FreezeHooksTestSupport freezeHooks_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_F(FreezeHooksTest, TypeWithFreezeHook) {
|
||||
TypeInfo type;
|
||||
type.typeInfo_ = &type;
|
||||
type.flags_ |= TF_HAS_FREEZE_HOOK;
|
||||
ObjHeader obj = {&type};
|
||||
EXPECT_CALL(freezeHook(), Call(&obj));
|
||||
RunFreezeHooks(&obj);
|
||||
testing::Mock::VerifyAndClearExpectations(&freezeHook());
|
||||
}
|
||||
|
||||
TEST_F(FreezeHooksTest, TypeWithoutFreezeHook) {
|
||||
TypeInfo type;
|
||||
type.typeInfo_ = &type;
|
||||
type.flags_ &= ~TF_HAS_FREEZE_HOOK;
|
||||
ObjHeader obj = {&type};
|
||||
EXPECT_CALL(freezeHook(), Call(_)).Times(0);
|
||||
RunFreezeHooks(&obj);
|
||||
testing::Mock::VerifyAndClearExpectations(&freezeHook());
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 "FreezeHooksTestSupport.hpp"
|
||||
|
||||
#include "FreezeHooks.hpp"
|
||||
|
||||
using namespace kotlin;
|
||||
|
||||
namespace {
|
||||
|
||||
testing::MockFunction<void(ObjHeader*)>* g_freezeHook = nullptr;
|
||||
|
||||
void freezeHook(ObjHeader* object) {
|
||||
g_freezeHook->Call(object);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
kotlin::FreezeHooksTestSupport::FreezeHooksTestSupport() {
|
||||
g_freezeHook = &freezeHook_;
|
||||
SetFreezeHookForTesting(&::freezeHook);
|
||||
}
|
||||
|
||||
kotlin::FreezeHooksTestSupport::~FreezeHooksTestSupport() {
|
||||
SetFreezeHookForTesting(nullptr);
|
||||
g_freezeHook = nullptr;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RUNTIME_MM_FREEZE_HOOKS_TEST_SUPPORT_H
|
||||
#define RUNTIME_MM_FREEZE_HOOKS_TEST_SUPPORT_H
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
struct ObjHeader;
|
||||
|
||||
namespace kotlin {
|
||||
|
||||
class FreezeHooksTestSupport {
|
||||
public:
|
||||
FreezeHooksTestSupport();
|
||||
~FreezeHooksTestSupport();
|
||||
|
||||
testing::MockFunction<void(ObjHeader*)>& freezeHook() { return freezeHook_; }
|
||||
|
||||
private:
|
||||
testing::StrictMock<testing::MockFunction<void(ObjHeader*)>> freezeHook_;
|
||||
};
|
||||
|
||||
} // namespace kotlin
|
||||
|
||||
#endif // RUNTIME_MM_FREEZE_HOOKS_TEST_SUPPORT_H
|
||||
@@ -63,6 +63,7 @@ enum Konan_TypeFlags {
|
||||
TF_LEAK_DETECTOR_CANDIDATE = 1 << 4,
|
||||
TF_SUSPEND_FUNCTION = 1 << 5,
|
||||
TF_HAS_FINALIZER = 1 << 6,
|
||||
TF_HAS_FREEZE_HOOK = 1 << 7,
|
||||
};
|
||||
|
||||
// Flags per object instance.
|
||||
|
||||
Reference in New Issue
Block a user