55#include < cmath>
66#include < ctime>
77#include < filesystem>
8- #include < iostream>
98#include < random>
109#include < ranges>
1110#include < sstream>
2120
2221#ifdef _WIN32
2322#include < windows.h>
23+
24+ #include < psapi.h>
25+ #elif __APPLE__
26+ #include < dlfcn.h>
27+ #include < unistd.h>
28+
29+ #include < mach/mach.h>
30+ #include < mach/task_info.h>
2431#else
2532#include < dlfcn.h>
33+ #include < sys/resource.h>
2634#include < unistd.h>
2735#endif
2836
@@ -109,10 +117,8 @@ std::expected<ExecutionResult, std::runtime_error> PushString(PassedExecutionDat
109117 return std::unexpected (vtable_index_result.error ());
110118 }
111119
112- auto string_obj_result = runtime::AllocateObject (*string_vtable,
113- static_cast <uint32_t >(vtable_index_result.value ()),
114- data.memory .object_repository ,
115- data.allocator );
120+ auto string_obj_result =
121+ data.memory_manager .AllocateObject (*string_vtable, static_cast <uint32_t >(vtable_index_result.value ()), data);
116122
117123 if (!string_obj_result.has_value ()) {
118124 return std::unexpected (string_obj_result.error ());
@@ -140,8 +146,8 @@ std::expected<ExecutionResult, std::runtime_error> PushNull(PassedExecutionData&
140146 return std::unexpected (vtable_index_result.error ());
141147 }
142148
143- auto null_obj_result = runtime::AllocateObject (
144- *null_vtable, static_cast <uint32_t >(vtable_index_result.value ()), data. memory . object_repository , data. allocator );
149+ auto null_obj_result =
150+ data. memory_manager . AllocateObject ( *null_vtable, static_cast <uint32_t >(vtable_index_result.value ()), data);
145151
146152 if (!null_obj_result.has_value ()) {
147153 return std::unexpected (null_obj_result.error ());
@@ -1211,8 +1217,7 @@ std::expected<ExecutionResult, std::runtime_error> CallConstructor(PassedExecuti
12111217 return std::unexpected (vtable.error ());
12121218 }
12131219
1214- auto obj_ptr =
1215- runtime::AllocateObject (*vtable.value (), vtable_idx.value (), data.memory .object_repository , data.allocator );
1220+ auto obj_ptr = data.memory_manager .AllocateObject (*vtable.value (), vtable_idx.value (), data);
12161221
12171222 if (!obj_ptr) {
12181223 return std::unexpected (obj_ptr.error ());
@@ -1452,7 +1457,7 @@ std::expected<ExecutionResult, std::runtime_error> NullCoalesce(PassedExecutionD
14521457
14531458 if (*tested_result_data != nullptr ) {
14541459 data.memory .machine_stack .pop ();
1455- data.memory .machine_stack .emplace (tested_result. value () );
1460+ data.memory .machine_stack .emplace (*tested_result_data );
14561461 }
14571462
14581463 return ExecutionResult::kNormal ;
@@ -1602,10 +1607,9 @@ std::expected<ExecutionResult, std::runtime_error> FormatDateTime(PassedExecutio
16021607 return std::unexpected (vtable_index_result.error ());
16031608 }
16041609
1605- auto string_obj_result = runtime::AllocateObject (*string_vtable,
1606- static_cast <uint32_t >(vtable_index_result.value ()),
1607- data.memory .object_repository ,
1608- data.allocator );
1610+ auto string_obj_result =
1611+ data.memory_manager .AllocateObject (*string_vtable, static_cast <uint32_t >(vtable_index_result.value ()), data);
1612+
16091613 if (!string_obj_result.has_value ()) {
16101614 return std::unexpected (string_obj_result.error ());
16111615 }
@@ -1659,8 +1663,9 @@ std::expected<ExecutionResult, std::runtime_error> ParseDateTime(PassedExecution
16591663 return std::unexpected (vtable_index_result.error ());
16601664 }
16611665
1662- auto int_obj_result = runtime::AllocateObject (
1663- *int_vtable, static_cast <uint32_t >(vtable_index_result.value ()), data.memory .object_repository , data.allocator );
1666+ auto int_obj_result =
1667+ data.memory_manager .AllocateObject (*int_vtable, static_cast <uint32_t >(vtable_index_result.value ()), data);
1668+
16641669 if (!int_obj_result.has_value ()) {
16651670 return std::unexpected (int_obj_result.error ());
16661671 }
@@ -1821,10 +1826,8 @@ std::expected<ExecutionResult, std::runtime_error> ListDir(PassedExecutionData&
18211826 return std::unexpected (vtable_index_result.error ());
18221827 }
18231828
1824- auto string_array_obj_result = runtime::AllocateObject (*string_array_vtable,
1825- static_cast <uint32_t >(vtable_index_result.value ()),
1826- data.memory .object_repository ,
1827- data.allocator );
1829+ auto string_array_obj_result = data.memory_manager .AllocateObject (
1830+ *string_array_vtable, static_cast <uint32_t >(vtable_index_result.value ()), data);
18281831 if (!string_array_obj_result.has_value ()) {
18291832 return std::unexpected (string_array_obj_result.error ());
18301833 }
@@ -1847,10 +1850,9 @@ std::expected<ExecutionResult, std::runtime_error> ListDir(PassedExecutionData&
18471850 return std::unexpected (string_vtable_index_result.error ());
18481851 }
18491852
1850- auto string_obj_result = runtime::AllocateObject (*string_vtable,
1851- static_cast <uint32_t >(string_vtable_index_result.value ()),
1852- data.memory .object_repository ,
1853- data.allocator );
1853+ auto string_obj_result = data.memory_manager .AllocateObject (
1854+ *string_vtable, static_cast <uint32_t >(string_vtable_index_result.value ()), data);
1855+
18541856 if (!string_obj_result.has_value ()) {
18551857 return std::unexpected (string_obj_result.error ());
18561858 }
@@ -2068,20 +2070,36 @@ std::expected<ExecutionResult, std::runtime_error> SeedRandom(PassedExecutionDat
20682070}
20692071
20702072std::expected<ExecutionResult, std::runtime_error> GetMemoryUsage (PassedExecutionData& data) {
2071- // Simple memory usage approximation
20722073 size_t memory_usage = 0 ;
20732074
2074- // Stack size
2075- memory_usage += data.memory .machine_stack .size () * sizeof (runtime::Variable);
2076-
2077- auto stack_copy = data.memory .stack_frames ;
2078- // Local variables in all stack frames
2079- while (!stack_copy.empty ()) {
2080- memory_usage += stack_copy.top ().local_variables .size () * sizeof (runtime::Variable);
2081- stack_copy.pop ();
2075+ #ifdef _WIN32
2076+ PROCESS_MEMORY_COUNTERS pmc;
2077+ if (GetProcessMemoryInfo (GetCurrentProcess (), &pmc, sizeof (pmc))) {
2078+ memory_usage = static_cast <size_t >(pmc.WorkingSetSize );
2079+ } else {
2080+ return std::unexpected (std::runtime_error (" GetMemoryUsage: failed to get process memory info" ));
2081+ }
2082+ #elif __APPLE__
2083+ struct task_basic_info info {};
2084+ mach_msg_type_number_t size = sizeof (info);
2085+ kern_return_t kerr = task_info (mach_task_self (), TASK_BASIC_INFO , reinterpret_cast <task_info_t >(&info), &size);
2086+ if (kerr == KERN_SUCCESS ) {
2087+ memory_usage = static_cast <size_t >(info.resident_size );
2088+ } else {
2089+ return std::unexpected (std::runtime_error (" GetMemoryUsage: failed to get task memory info" ));
2090+ }
2091+ #else
2092+ // Linux: Use getrusage() system call
2093+ struct rusage usage {};
2094+ constexpr size_t kBytesInRusageUnit = 1024 ;
2095+ if (getrusage (RUSAGE_SELF , &usage) != 0 ) {
2096+ return std::unexpected (std::runtime_error (" GetMemoryUsage: getrusage() failed" ));
20822097 }
20832098
2084- // TODO counter for repositories
2099+ // ru_maxrss is the maximum resident set size in kilobytes
2100+ // Note: getrusage gives maximum usage, not current usage
2101+ memory_usage = static_cast <size_t >(usage.ru_maxrss ) * kBytesInRusageUnit ;
2102+ #endif
20852103
20862104 data.memory .machine_stack .emplace (static_cast <int64_t >(memory_usage));
20872105 return ExecutionResult::kNormal ;
@@ -2094,8 +2112,10 @@ std::expected<ExecutionResult, std::runtime_error> GetPeakMemoryUsage(PassedExec
20942112
20952113std::expected<ExecutionResult, std::runtime_error> ForceGarbageCollection (PassedExecutionData& data) {
20962114 // Simple garbage collection: remove unreachable objects
2097- // This is a placeholder implementation
2098- // data.memory.object_repository.CollectGarbage();
2115+ auto result = data.memory_manager .CollectGarbage (data);
2116+ if (!result.has_value ()) {
2117+ return std::unexpected (result.error ());
2118+ }
20992119 return ExecutionResult::kNormal ;
21002120}
21012121
0 commit comments