Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0fb2906
add K2 confdata key splitting and wildcard metadata
apolyakov Aug 20, 2026
3de422c
port kPHP confdata test matrices to runtime-light
apolyakov Aug 20, 2026
bc2c32e
add K2 script memory resource switching
apolyakov Aug 21, 2026
2da3792
add shared memory confdata storage
apolyakov Aug 21, 2026
a8c2db6
add memory_resource::stl::forward_list
apolyakov Aug 27, 2026
829d150
Implement shared-memory confdata storage for K2
apolyakov Sep 1, 2026
347dfd0
support OOM handling size in confdata
apolyakov Sep 2, 2026
61feadc
remove temporary k2::free_shared_memory
apolyakov Sep 2, 2026
6968c31
add temporary [[maybe_unused]]
apolyakov Sep 2, 2026
86fc0bb
init confdata only if it's available
apolyakov Sep 2, 2026
3b33c98
reduce confdata memory usage during clean sync
apolyakov Sep 4, 2026
a5d9378
revert change of k2-header version
apolyakov Sep 7, 2026
da3b541
add diagnostic logs
apolyakov Sep 8, 2026
c805dd9
fix confdata availability check
apolyakov Sep 8, 2026
b393c6b
nfc to confdata
apolyakov Sep 9, 2026
eda28e4
use kphp-confdata instead of confdata
apolyakov Sep 9, 2026
359c4f6
fix any wildcards
apolyakov Sep 9, 2026
9180eb6
fix tests linking
apolyakov Sep 10, 2026
f60096f
get rid of K2 unit tests for now
apolyakov Sep 10, 2026
4ee8998
update allocators
apolyakov Sep 10, 2026
2e37441
update confdata version
apolyakov Sep 10, 2026
4dc928e
rename K2_CONFDATA_* to KPHP_CONFDATA_*
apolyakov Sep 10, 2026
90961b0
minor changes to constants
apolyakov Sep 10, 2026
f98203e
add missing sources
apolyakov Sep 10, 2026
abecc07
add missing define to compiler
apolyakov Sep 10, 2026
884b29a
link light-common to confdata
apolyakov Sep 10, 2026
4ae00bf
add missing include
apolyakov Sep 10, 2026
cb9ff2e
add kphp-confdata.so to install targets
apolyakov Sep 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ endif()
add_custom_target(kphp ALL DEPENDS ${OBJS_DIR}/php_lib_version.sha256)

if (COMPILE_RUNTIME_LIGHT)
add_dependencies(kphp kphp2cpp kphp-light-runtime-pic)
add_dependencies(kphp kphp2cpp kphp-light-runtime-pic kphp-confdata-pic)
else ()
add_dependencies(kphp kphp2cpp kphp-full-runtime-no-pic kphp-full-runtime-pic)
endif ()
Expand All @@ -95,6 +95,10 @@ install_symlink(${VK_INSTALL_DIR}/bin/kphp2cpp ${CMAKE_INSTALL_PREFIX}/bin/kphp

# k2 specific
if(COMPILE_RUNTIME_LIGHT)
install(TARGETS kphp-confdata-pic
LIBRARY DESTINATION ${INSTALL_KPHP_SOURCE}/objs
COMPONENT KPHP)

install(FILES ${OBJS_DIR}/libk2kphp-rt.a
COMPONENT KPHP
DESTINATION ${INSTALL_KPHP_SOURCE}/objs)
Expand Down
3 changes: 0 additions & 3 deletions builtin-functions/kphp-light/stdlib/confdata-functions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@

function is_confdata_loaded(): bool;

/** @kphp-extern-func-info interruptible */
function confdata_get_value($key ::: string): mixed;

/** @kphp-extern-func-info interruptible */
function confdata_get_values_by_any_wildcard($wildcard ::: string): mixed[];

/** @kphp-extern-func-info interruptible */
function confdata_get_values_by_predefined_wildcard($wildcard ::: string): mixed[];
2 changes: 2 additions & 0 deletions compiler/compiler-settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,8 @@ void CompilerSettings::init() {

ss << " -I" << kphp_src_path.get() + "objs/include ";
if (is_k2_mode) {
// Generated code and its precompiled header must use the light runtime declarations.
ss << " -DRUNTIME_LIGHT";
// for now k2-component must be compiled with clang and statically linked libc++
ss << " -stdlib=libc++";
if (!dynamic_incremental_linkage.get()) {
Expand Down
12 changes: 10 additions & 2 deletions runtime-common/core/allocator/pool-allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,25 @@
namespace kphp::memory {

struct pool_allocator : private vk::not_copyable {
struct external_memory {};

private:
enum class memory_mode {
owned_growable,
external_fixed, // Never grows or releases the externally owned backing buffer.
};

memory_resource::unsynchronized_pool_resource memory_resource;
memory_mode m_memory_mode{memory_mode::owned_growable};
size_t m_min_extra_mem_size{0};

auto request_extra_memory(size_t requested_size) noexcept -> void;

public:
pool_allocator() = default;
pool_allocator(size_t script_mem_size, size_t min_extra_mem_size, size_t oom_handling_mem_size) noexcept;
// Borrows the buffer without growing it or releasing it in free().
pool_allocator(external_memory, void* buffer, size_t script_mem_size, size_t oom_handling_mem_size) noexcept;

auto init(void* buffer, size_t script_mem_size, size_t oom_handling_mem_size) noexcept -> void;
auto free() noexcept -> void;

auto alloc_script_memory(size_t size) noexcept -> void*;
Expand Down
38 changes: 32 additions & 6 deletions runtime-common/core/allocator/runtime-allocator.h
Original file line number Diff line number Diff line change
@@ -1,32 +1,58 @@
// Compiler for PHP (aka KPHP)
// Copyright (c) 2024 LLC «V Kontakte»
// Distributed under the GPL v3 License, see LICENSE.notice.txt
// Compiler for PHP (aka KPHP)
// Copyright (c) 2024 LLC «V Kontakte»
// Distributed under the GPL v3 License, see LICENSE.notice.txt

#pragma once

#include <cstddef>
#ifdef RUNTIME_LIGHT
#include <cstdint>
#include <functional>
#include <type_traits>
#include <utility>

#include "common/containers/final_action.h"
#include "runtime-common/core/allocator/pool-allocator.h"
#endif

struct RuntimeAllocator final {
#ifdef RUNTIME_LIGHT
private:
kphp::memory::pool_allocator m_allocator;
std::reference_wrapper<kphp::memory::pool_allocator> m_allocator_ref{m_allocator};
#endif

public:
static auto get() noexcept -> RuntimeAllocator&;

RuntimeAllocator() = default;
#ifdef RUNTIME_LIGHT
RuntimeAllocator(size_t script_mem_size, size_t min_extra_mem_size, size_t oom_handling_mem_size) noexcept;

#else
RuntimeAllocator() = default;
auto init(void* buffer, size_t script_mem_size, size_t oom_handling_mem_size) noexcept -> void;
#endif

auto free() noexcept -> void;

auto alloc_script_memory(size_t size) noexcept -> void*;
auto calloc_script_memory(size_t size) noexcept -> void*;
auto realloc_script_memory(void* mem, size_t new_size, size_t old_size) noexcept -> void*;
auto free_script_memory(void* mem, size_t size) noexcept -> void;

#ifdef RUNTIME_LIGHT
auto get_memory_resource() noexcept -> memory_resource::unsynchronized_pool_resource& {
return m_allocator.get_memory_resource();
return m_allocator_ref.get().get_memory_resource();
}

// The callback must run synchronously without yielding. Objects allocated by it
// may outlive the scope, but later operations that allocate or deallocate their
// memory must install the same allocator. The replacement must outlive the callback.
template<typename callback_type,
std::enable_if_t<std::is_nothrow_invocable_v<callback_type> && std::is_same_v<std::invoke_result_t<callback_type>, void>, int32_t> = 0>
auto with_allocator(kphp::memory::pool_allocator& replacement, callback_type&& callback) noexcept -> void {
const auto previous_allocator{std::exchange(m_allocator_ref, std::ref(replacement))};
const auto restore_allocator{vk::finally([this, previous_allocator]() noexcept { m_allocator_ref = previous_allocator; })};
std::invoke(std::forward<callback_type>(callback));
}
#endif
};
4 changes: 4 additions & 0 deletions runtime-common/core/memory-resource/resource_allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#pragma once

#include <forward_list>
#include <functional>
#include <list>
#include <map>
Expand Down Expand Up @@ -88,6 +89,9 @@ using vector = std::vector<T, resource_allocator<T, Resource>>;
template<class T, class Resource>
using list = std::list<T, resource_allocator<T, Resource>>;

template<class T, class Resource>
using forward_list = std::forward_list<T, resource_allocator<T, Resource>>;

template<class Resource>
using string = std::basic_string<char, std::char_traits<char>, resource_allocator<char, Resource>>;
} // namespace stl
Expand Down
4 changes: 4 additions & 0 deletions runtime-common/core/std/containers.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#pragma once

#include <deque>
#include <forward_list>
#include <functional>
#include <list>
#include <map>
Expand Down Expand Up @@ -41,6 +42,9 @@ using queue = std::queue<T, std::deque<T, Allocator<T>>>;
template<class T, template<class> class Allocator>
using list = std::list<T, Allocator<T>>;

template<class T, template<class> class Allocator>
using forward_list = std::forward_list<T, Allocator<T>>;

template<class T, template<class> class Allocator>
using vector = std::vector<T, Allocator<T>>;

Expand Down
4 changes: 3 additions & 1 deletion runtime-light/allocator/allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
#pragma once

#include <concepts>
#include <cstddef>
#include <memory>
#include <utility>

#include "runtime-common/core/allocator/script-allocator-managed.h"
#include "runtime-light/allocator/allocator-state.h"
Expand All @@ -17,6 +18,7 @@ auto make_unique_on_script_memory(Args&&... args) noexcept {
}

namespace kphp::memory {

struct libc_alloc_guard final {
libc_alloc_guard() noexcept {
AllocatorState::get_mutable().enable_libc_alloc();
Expand Down
22 changes: 9 additions & 13 deletions runtime-light/allocator/pool-allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,22 @@ namespace kphp::memory {

pool_allocator::pool_allocator(size_t script_mem_size, size_t min_extra_mem_size, size_t oom_handling_mem_size) noexcept
: m_min_extra_mem_size(min_extra_mem_size) {
// kphp::log::debug("create pool allocator -> {:p}: script memory -> {}, oom handling size -> {}", reinterpret_cast<void*>(this), script_mem_size,
// oom_handling_mem_size);
void* buffer{kphp::memory::platform::alloc(script_mem_size)};

kphp::log::assertion(buffer != nullptr);

memory_resource.init(buffer, script_mem_size, oom_handling_mem_size);
}

auto pool_allocator::init(void* buffer, size_t script_mem_size, size_t oom_handling_mem_size) noexcept -> void {
pool_allocator::pool_allocator(external_memory /*unused*/, void* buffer, size_t script_mem_size, size_t oom_handling_mem_size) noexcept
: m_memory_mode{memory_mode::external_fixed} {
kphp::log::assertion(buffer != nullptr);

// kphp::log::debug("init pool allocator -> {:p}: buffer -> {:p}, script memory -> {}, oom handling size -> {}", reinterpret_cast<void*>(this), buffer,
// script_mem_size, oom_handling_mem_size);
memory_resource.init(buffer, script_mem_size, oom_handling_mem_size);
}

auto pool_allocator::free() noexcept -> void {
// kphp::log::debug("free pool allocator -> {:p}", reinterpret_cast<void*>(this));
if (m_memory_mode == memory_mode::external_fixed) {
return;
}

auto* extra_memory{memory_resource.get_extra_memory_head()};
while (extra_memory->get_pool_payload_size() != 0) {
auto* extra_memory_to_release{extra_memory};
Expand Down Expand Up @@ -94,6 +91,9 @@ auto pool_allocator::free_script_memory(void* mem, size_t size) noexcept -> void
}

auto pool_allocator::request_extra_memory(size_t requested_size) noexcept -> void {
// Fixed pools must fail on exhaustion instead of allocating outside their buffer.
kphp::log::assertion(m_memory_mode == memory_mode::owned_growable);

// Extra mem size have to be greater than max chunk block
const auto min_size{std::max(m_min_extra_mem_size, memory_resource::unsynchronized_pool_resource::MAX_CHUNK_BLOCK_SIZE)};

Expand All @@ -103,12 +103,8 @@ auto pool_allocator::request_extra_memory(size_t requested_size) noexcept -> voi
// The smallest power of two that is not smaller than `extra_mem_size`
extra_mem_size = std::bit_ceil(extra_mem_size);

// kphp::log::debug("requested extra memory pool with size {} bytes, will be allocated {} bytes", requested_size, extra_mem_size);

auto* extra_mem{kphp::memory::platform::alloc(extra_mem_size)};

kphp::log::assertion(extra_mem != nullptr);

memory_resource.add_extra_memory(new (extra_mem) memory_resource::extra_memory_pool{extra_mem_size});
}

Expand Down
13 changes: 4 additions & 9 deletions runtime-light/allocator/runtime-light-allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// Distributed under the GPL v3 License, see LICENSE.notice.txt

#include "runtime-common/core/allocator/runtime-allocator.h"

#include "runtime-light/allocator/allocator-state.h"

auto RuntimeAllocator::get() noexcept -> RuntimeAllocator& {
Expand All @@ -13,26 +12,22 @@ auto RuntimeAllocator::get() noexcept -> RuntimeAllocator& {
RuntimeAllocator::RuntimeAllocator(size_t script_mem_size, size_t min_extra_mem_size, size_t oom_handling_mem_size) noexcept
: m_allocator{script_mem_size, min_extra_mem_size, oom_handling_mem_size} {}

auto RuntimeAllocator::init(void* buffer, size_t script_mem_size, size_t oom_handling_mem_size) noexcept -> void {
m_allocator.init(buffer, script_mem_size, oom_handling_mem_size);
}

auto RuntimeAllocator::free() noexcept -> void {
m_allocator.free();
}

auto RuntimeAllocator::alloc_script_memory(size_t size) noexcept -> void* {
return m_allocator.alloc_script_memory(size);
return m_allocator_ref.get().alloc_script_memory(size);
}

auto RuntimeAllocator::calloc_script_memory(size_t size) noexcept -> void* {
return m_allocator.calloc_script_memory(size);
return m_allocator_ref.get().calloc_script_memory(size);
}

auto RuntimeAllocator::realloc_script_memory(void* mem, size_t new_size, size_t old_size) noexcept -> void* {
return m_allocator.realloc_script_memory(mem, new_size, old_size);
return m_allocator_ref.get().realloc_script_memory(mem, new_size, old_size);
}

auto RuntimeAllocator::free_script_memory(void* mem, size_t size) noexcept -> void {
m_allocator.free_script_memory(mem, size);
m_allocator_ref.get().free_script_memory(mem, size);
}
8 changes: 4 additions & 4 deletions runtime-light/components/confdata/confdata-component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@ VISIBILITY_DEFAULT k2::PollStatus k2_poll() {
}

VISIBILITY_DEFAULT const ImageInfo* k2_describe() {
static constexpr std::array extra_info{ImageInfo::KeyValuePair{.key = "compiler_version", .value = K2_CONFDATA_COMPILER_VERSION}};
static constexpr ImageInfo image_info{.image_name = kphp::confdata::COMPONENT_NAME.data(),
static constexpr std::array extra_info{ImageInfo::KeyValuePair{.key = "compiler_version", .value = KPHP_CONFDATA_COMPILER_VERSION}};
static constexpr ImageInfo image_info{.image_name = kphp::confdata::IMAGE_NAME.data(),
.is_oneshot = 0,
.build_timestamp = K2_CONFDATA_BUILD_TIMESTAMP,
.build_timestamp = KPHP_CONFDATA_BUILD_TIMESTAMP,
.header_h_version = K2_PLATFORM_HEADER_H_VERSION,
.version = "0.0.1",
.version = "1.0.0",
.extra_info_size = extra_info.size(),
.extra_info = extra_info.data()};
return std::addressof(image_info);
Expand Down
Loading
Loading