Sketch mm::ObjectFactory (#4583)

This commit is contained in:
Alexander Shabalin
2020-12-21 19:12:21 +03:00
committed by Nikolay Krasko
parent d239ff7f5a
commit 72fc5f5aee
11 changed files with 1181 additions and 12 deletions
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2020 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_ALIGNMENT_H
#define RUNTIME_ALIGNMENT_H
#include <cstddef>
#include <cstdint>
namespace kotlin {
constexpr size_t kObjectAlignment = 8;
constexpr inline size_t AlignUp(size_t size, size_t alignment) {
return (size + alignment - 1) & ~(alignment - 1);
}
inline void* AlignUp(void* ptr, size_t alignment) {
static_assert(sizeof(void*) == sizeof(size_t), "size_t size must be equal to pointer size for this to work");
return reinterpret_cast<void*>(AlignUp(reinterpret_cast<size_t>(ptr), alignment));
}
constexpr inline bool IsValidAlignment(size_t alignment) {
return alignment != 0 && (alignment & (alignment - 1)) == 0;
}
constexpr inline bool IsAligned(size_t size, size_t alignment) {
return size % alignment == 0;
}
inline bool IsAligned(void* ptr, size_t alignment) {
return reinterpret_cast<uintptr_t>(ptr) % alignment == 0;
}
} // namespace kotlin
#endif // RUNTIME_ALIGNMENT_H
@@ -0,0 +1,157 @@
/*
* Copyright 2010-2020 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 "Alignment.hpp"
#include <cstddef>
#include <tuple>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "Types.h"
using namespace kotlin;
namespace {
template <typename... Args>
class NamedTestWithParam : public testing::TestWithParam<std::tuple<const char*, Args...>> {
public:
using Param = std::tuple<const char*, Args...>;
static std::string Print(const testing::TestParamInfo<Param>& info) { return std::string(std::get<0>(info.param)); }
template <size_t I>
static const typename std::tuple_element<I + 1, Param>::type& Get() {
const auto& param = testing::TestWithParam<Param>::GetParam();
return std::get<I + 1>(param);
}
};
#define INSTANTIATE_NAMED_TEST(testName, ...) INSTANTIATE_TEST_SUITE_P(, testName, testing::Values(__VA_ARGS__), &testName::Print)
} // namespace
using IsValidAlignmentTest = NamedTestWithParam<size_t, bool>;
TEST_P(IsValidAlignmentTest, Test) {
const auto& alignment = Get<0>();
const auto& expected = Get<1>();
EXPECT_THAT(IsValidAlignment(alignment), expected);
}
INSTANTIATE_NAMED_TEST(
IsValidAlignmentTest,
std::make_tuple("0", 0, false),
std::make_tuple("1", 1, true),
std::make_tuple("2", 2, true),
std::make_tuple("3", 3, false),
std::make_tuple("4", 4, true),
std::make_tuple("5", 5, false),
std::make_tuple("6", 6, false),
std::make_tuple("7", 7, false),
std::make_tuple("8", 8, true),
std::make_tuple("9", 9, false),
std::make_tuple("10", 10, false),
std::make_tuple("11", 11, false),
std::make_tuple("12", 12, false),
std::make_tuple("13", 13, false),
std::make_tuple("14", 14, false),
std::make_tuple("15", 15, false),
std::make_tuple("16", 16, true),
std::make_tuple("int", alignof(int), true),
std::make_tuple("ptr", alignof(void*), true),
std::make_tuple("max", alignof(std::max_align_t), true));
using IsAlignedSizeTest = NamedTestWithParam<size_t, size_t, bool>;
TEST_P(IsAlignedSizeTest, Test) {
const auto& size = Get<0>();
const auto& alignment = Get<1>();
const auto& expected = Get<2>();
EXPECT_THAT(IsAligned(size, alignment), expected);
}
INSTANTIATE_NAMED_TEST(
IsAlignedSizeTest,
std::make_tuple("1_1", 1, 1, true),
std::make_tuple("2_1", 2, 1, true),
std::make_tuple("3_1", 3, 1, true),
std::make_tuple("4_1", 4, 1, true),
std::make_tuple("1_2", 1, 2, false),
std::make_tuple("2_2", 2, 2, true),
std::make_tuple("3_2", 3, 2, false),
std::make_tuple("4_2", 4, 2, true));
using IsAlignedPointerTest = NamedTestWithParam<uintptr_t, size_t, bool>;
TEST_P(IsAlignedPointerTest, Test) {
const auto& ptr = Get<0>();
const auto& alignment = Get<1>();
const auto& expected = Get<2>();
EXPECT_THAT(IsAligned(reinterpret_cast<void*>(ptr), alignment), expected);
}
INSTANTIATE_NAMED_TEST(
IsAlignedPointerTest,
std::make_tuple("0_1", 0, 1, true),
std::make_tuple("1_1", 1, 1, true),
std::make_tuple("2_1", 2, 1, true),
std::make_tuple("3_1", 3, 1, true),
std::make_tuple("4_1", 4, 1, true),
std::make_tuple("0_2", 0, 2, true),
std::make_tuple("1_2", 1, 2, false),
std::make_tuple("2_2", 2, 2, true),
std::make_tuple("3_2", 3, 2, false),
std::make_tuple("4_2", 4, 2, true));
using AlignUpSizeTest = NamedTestWithParam<size_t, size_t, size_t>;
TEST_P(AlignUpSizeTest, Test) {
const auto& size = Get<0>();
const auto& alignment = Get<1>();
const auto& expected = Get<2>();
EXPECT_THAT(AlignUp(size, alignment), expected);
}
INSTANTIATE_NAMED_TEST(
AlignUpSizeTest,
std::make_tuple("1_1", 1, 1, 1),
std::make_tuple("2_1", 2, 1, 2),
std::make_tuple("3_1", 3, 1, 3),
std::make_tuple("4_1", 4, 1, 4),
std::make_tuple("1_2", 1, 2, 2),
std::make_tuple("2_2", 2, 2, 2),
std::make_tuple("3_2", 3, 2, 4),
std::make_tuple("4_2", 4, 2, 4));
using AlignUpPointerTest = NamedTestWithParam<uintptr_t, size_t, uintptr_t>;
TEST_P(AlignUpPointerTest, Test) {
const auto& ptr = Get<0>();
const auto& alignment = Get<1>();
const auto& expected = Get<2>();
EXPECT_THAT(AlignUp(reinterpret_cast<void*>(ptr), alignment), reinterpret_cast<void*>(expected));
}
INSTANTIATE_NAMED_TEST(
AlignUpPointerTest,
std::make_tuple("0_1", 0, 1, 0),
std::make_tuple("1_1", 1, 1, 1),
std::make_tuple("2_1", 2, 1, 2),
std::make_tuple("3_1", 3, 1, 3),
std::make_tuple("4_1", 4, 1, 4),
std::make_tuple("0_2", 0, 2, 0),
std::make_tuple("1_2", 1, 2, 2),
std::make_tuple("2_2", 2, 2, 2),
std::make_tuple("3_2", 3, 2, 4),
std::make_tuple("4_2", 4, 2, 4));
TEST(AlignmentTest, ObjectAlignment) {
static_assert(IsValidAlignment(kObjectAlignment), "kObjectAlignment must be a valid alignment");
static_assert(kObjectAlignment % alignof(KLong) == 0, "");
static_assert(kObjectAlignment % alignof(KDouble) == 0, "");
}
@@ -29,6 +29,10 @@ 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);
}
@@ -157,6 +157,8 @@ struct TypeInfo {
inline VTableElement* vtable() {
return reinterpret_cast<VTableElement*>(this + 1);
}
inline bool IsArray() const { return instanceSize_ < 0; }
#endif
};