zexus 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +0 -0
- package/README.md +2513 -0
- package/bin/zexus +2 -0
- package/bin/zpics +2 -0
- package/bin/zpm +2 -0
- package/bin/zx +2 -0
- package/bin/zx-deploy +2 -0
- package/bin/zx-dev +2 -0
- package/bin/zx-run +2 -0
- package/package.json +66 -0
- package/scripts/README.md +24 -0
- package/scripts/postinstall.js +44 -0
- package/shared_config.json +24 -0
- package/src/README.md +1525 -0
- package/src/tests/run_zexus_tests.py +117 -0
- package/src/tests/test_all_phases.zx +346 -0
- package/src/tests/test_blockchain_features.zx +306 -0
- package/src/tests/test_complexity_features.zx +321 -0
- package/src/tests/test_core_integration.py +185 -0
- package/src/tests/test_phase10_ecosystem.zx +177 -0
- package/src/tests/test_phase1_modifiers.zx +87 -0
- package/src/tests/test_phase2_plugins.zx +80 -0
- package/src/tests/test_phase3_security.zx +97 -0
- package/src/tests/test_phase4_vfs.zx +116 -0
- package/src/tests/test_phase5_types.zx +117 -0
- package/src/tests/test_phase6_metaprogramming.zx +125 -0
- package/src/tests/test_phase7_optimization.zx +132 -0
- package/src/tests/test_phase9_advanced_types.zx +157 -0
- package/src/tests/test_security_features.py +419 -0
- package/src/tests/test_security_features.zx +276 -0
- package/src/tests/test_simple_zx.zx +1 -0
- package/src/tests/test_verification_simple.zx +69 -0
- package/src/zexus/__init__.py +28 -0
- package/src/zexus/__main__.py +5 -0
- package/src/zexus/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/advanced_types.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/builtin_modules.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/capability_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/complexity_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/concurrency_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/config.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/dependency_injection.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/ecosystem.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/environment.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/error_reporter.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/hybrid_orchestrator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/metaprogramming.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/module_cache.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/object.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/optimization.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/plugin_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/policy_engine.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/security.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/stdlib_integration.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/strategy_recovery.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/syntax_validator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/type_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/virtual_filesystem.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/zexus_token.cpython-312.pyc +0 -0
- package/src/zexus/advanced_types.py +401 -0
- package/src/zexus/blockchain/__init__.py +40 -0
- package/src/zexus/blockchain/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/crypto.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/ledger.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/transaction.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/crypto.py +463 -0
- package/src/zexus/blockchain/ledger.py +255 -0
- package/src/zexus/blockchain/transaction.py +267 -0
- package/src/zexus/builtin_modules.py +284 -0
- package/src/zexus/builtin_plugins.py +317 -0
- package/src/zexus/capability_system.py +372 -0
- package/src/zexus/cli/__init__.py +2 -0
- package/src/zexus/cli/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/cli/__pycache__/main.cpython-312.pyc +0 -0
- package/src/zexus/cli/main.py +707 -0
- package/src/zexus/cli/zpm.py +203 -0
- package/src/zexus/compare_interpreter_compiler.py +146 -0
- package/src/zexus/compiler/__init__.py +169 -0
- package/src/zexus/compiler/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/parser.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/compiler/bytecode.py +266 -0
- package/src/zexus/compiler/compat_runtime.py +277 -0
- package/src/zexus/compiler/lexer.py +257 -0
- package/src/zexus/compiler/parser.py +779 -0
- package/src/zexus/compiler/semantic.py +118 -0
- package/src/zexus/compiler/zexus_ast.py +454 -0
- package/src/zexus/complexity_system.py +575 -0
- package/src/zexus/concurrency_system.py +493 -0
- package/src/zexus/config.py +201 -0
- package/src/zexus/crypto_bridge.py +19 -0
- package/src/zexus/dependency_injection.py +423 -0
- package/src/zexus/ecosystem.py +434 -0
- package/src/zexus/environment.py +101 -0
- package/src/zexus/environment_manager.py +119 -0
- package/src/zexus/error_reporter.py +314 -0
- package/src/zexus/evaluator/__init__.py +12 -0
- package/src/zexus/evaluator/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/bytecode_compiler.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/core.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/expressions.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/functions.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/integration.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/statements.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/utils.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/bytecode_compiler.py +700 -0
- package/src/zexus/evaluator/core.py +891 -0
- package/src/zexus/evaluator/expressions.py +827 -0
- package/src/zexus/evaluator/functions.py +3989 -0
- package/src/zexus/evaluator/integration.py +396 -0
- package/src/zexus/evaluator/statements.py +4303 -0
- package/src/zexus/evaluator/utils.py +126 -0
- package/src/zexus/evaluator_original.py +2041 -0
- package/src/zexus/external_bridge.py +16 -0
- package/src/zexus/find_affected_imports.sh +155 -0
- package/src/zexus/hybrid_orchestrator.py +152 -0
- package/src/zexus/input_validation.py +259 -0
- package/src/zexus/lexer.py +571 -0
- package/src/zexus/logging.py +89 -0
- package/src/zexus/lsp/__init__.py +9 -0
- package/src/zexus/lsp/completion_provider.py +207 -0
- package/src/zexus/lsp/definition_provider.py +22 -0
- package/src/zexus/lsp/hover_provider.py +71 -0
- package/src/zexus/lsp/server.py +269 -0
- package/src/zexus/lsp/symbol_provider.py +31 -0
- package/src/zexus/metaprogramming.py +321 -0
- package/src/zexus/module_cache.py +89 -0
- package/src/zexus/module_manager.py +107 -0
- package/src/zexus/object.py +973 -0
- package/src/zexus/optimization.py +424 -0
- package/src/zexus/parser/__init__.py +31 -0
- package/src/zexus/parser/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/parser.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/strategy_context.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/strategy_structural.cpython-312.pyc +0 -0
- package/src/zexus/parser/integration.py +86 -0
- package/src/zexus/parser/parser.py +3977 -0
- package/src/zexus/parser/strategy_context.py +7254 -0
- package/src/zexus/parser/strategy_structural.py +1033 -0
- package/src/zexus/persistence.py +391 -0
- package/src/zexus/plugin_system.py +290 -0
- package/src/zexus/policy_engine.py +365 -0
- package/src/zexus/profiler/__init__.py +5 -0
- package/src/zexus/profiler/profiler.py +233 -0
- package/src/zexus/purity_system.py +398 -0
- package/src/zexus/runtime/__init__.py +20 -0
- package/src/zexus/runtime/async_runtime.py +324 -0
- package/src/zexus/search_old_imports.sh +65 -0
- package/src/zexus/security.py +1407 -0
- package/src/zexus/stack_trace.py +233 -0
- package/src/zexus/stdlib/__init__.py +27 -0
- package/src/zexus/stdlib/blockchain.py +341 -0
- package/src/zexus/stdlib/compression.py +167 -0
- package/src/zexus/stdlib/crypto.py +124 -0
- package/src/zexus/stdlib/datetime.py +163 -0
- package/src/zexus/stdlib/db_mongo.py +199 -0
- package/src/zexus/stdlib/db_mysql.py +162 -0
- package/src/zexus/stdlib/db_postgres.py +163 -0
- package/src/zexus/stdlib/db_sqlite.py +133 -0
- package/src/zexus/stdlib/encoding.py +230 -0
- package/src/zexus/stdlib/fs.py +195 -0
- package/src/zexus/stdlib/http.py +219 -0
- package/src/zexus/stdlib/http_server.py +248 -0
- package/src/zexus/stdlib/json_module.py +61 -0
- package/src/zexus/stdlib/math.py +360 -0
- package/src/zexus/stdlib/os_module.py +265 -0
- package/src/zexus/stdlib/regex.py +148 -0
- package/src/zexus/stdlib/sockets.py +253 -0
- package/src/zexus/stdlib/test_framework.zx +208 -0
- package/src/zexus/stdlib/test_runner.zx +119 -0
- package/src/zexus/stdlib_integration.py +341 -0
- package/src/zexus/strategy_recovery.py +256 -0
- package/src/zexus/syntax_validator.py +356 -0
- package/src/zexus/testing/zpics.py +407 -0
- package/src/zexus/testing/zpics_runtime.py +369 -0
- package/src/zexus/type_system.py +374 -0
- package/src/zexus/validation_system.py +569 -0
- package/src/zexus/virtual_filesystem.py +355 -0
- package/src/zexus/vm/__init__.py +8 -0
- package/src/zexus/vm/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/async_optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/bytecode.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/cache.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/jit.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/memory_manager.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/memory_pool.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/parallel_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/peephole_optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/profiler.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/register_allocator.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/register_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/ssa_converter.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/async_optimizer.py +420 -0
- package/src/zexus/vm/bytecode.py +428 -0
- package/src/zexus/vm/bytecode_converter.py +297 -0
- package/src/zexus/vm/cache.py +532 -0
- package/src/zexus/vm/jit.py +720 -0
- package/src/zexus/vm/memory_manager.py +520 -0
- package/src/zexus/vm/memory_pool.py +511 -0
- package/src/zexus/vm/optimizer.py +478 -0
- package/src/zexus/vm/parallel_vm.py +899 -0
- package/src/zexus/vm/peephole_optimizer.py +452 -0
- package/src/zexus/vm/profiler.py +527 -0
- package/src/zexus/vm/register_allocator.py +462 -0
- package/src/zexus/vm/register_vm.py +520 -0
- package/src/zexus/vm/ssa_converter.py +757 -0
- package/src/zexus/vm/vm.py +1392 -0
- package/src/zexus/zexus_ast.py +1782 -0
- package/src/zexus/zexus_token.py +253 -0
- package/src/zexus/zpm/__init__.py +15 -0
- package/src/zexus/zpm/installer.py +116 -0
- package/src/zexus/zpm/package_manager.py +208 -0
- package/src/zexus/zpm/publisher.py +98 -0
- package/src/zexus/zpm/registry.py +110 -0
- package/src/zexus.egg-info/PKG-INFO +2235 -0
- package/src/zexus.egg-info/SOURCES.txt +876 -0
- package/src/zexus.egg-info/dependency_links.txt +1 -0
- package/src/zexus.egg-info/entry_points.txt +3 -0
- package/src/zexus.egg-info/not-zip-safe +1 -0
- package/src/zexus.egg-info/requires.txt +14 -0
- package/src/zexus.egg-info/top_level.txt +2 -0
- package/zexus.json +14 -0
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Zexus Memory Manager - Phase 7 Implementation
|
|
3
|
+
|
|
4
|
+
Provides memory management and garbage collection for the Zexus VM.
|
|
5
|
+
|
|
6
|
+
Features:
|
|
7
|
+
- Custom heap allocator with object pools
|
|
8
|
+
- Mark-and-sweep garbage collection
|
|
9
|
+
- Memory profiling and statistics
|
|
10
|
+
- Leak detection and prevention
|
|
11
|
+
- Configurable GC thresholds
|
|
12
|
+
|
|
13
|
+
Author: Zexus Team
|
|
14
|
+
Date: December 19, 2025
|
|
15
|
+
Version: 1.0
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import time
|
|
19
|
+
import weakref
|
|
20
|
+
from typing import Any, Dict, List, Set, Optional, Tuple
|
|
21
|
+
from dataclasses import dataclass, field
|
|
22
|
+
from enum import Enum
|
|
23
|
+
import sys
|
|
24
|
+
import gc as system_gc
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ObjectState(Enum):
|
|
28
|
+
"""Object lifecycle states"""
|
|
29
|
+
ALLOCATED = "allocated"
|
|
30
|
+
MARKED = "marked"
|
|
31
|
+
SWEPT = "swept"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass
|
|
35
|
+
class MemoryObject:
|
|
36
|
+
"""Managed memory object"""
|
|
37
|
+
id: int
|
|
38
|
+
obj: Any
|
|
39
|
+
size: int
|
|
40
|
+
allocated_at: float
|
|
41
|
+
state: ObjectState = ObjectState.ALLOCATED
|
|
42
|
+
ref_count: int = 0
|
|
43
|
+
generation: int = 0
|
|
44
|
+
|
|
45
|
+
def __hash__(self):
|
|
46
|
+
return self.id
|
|
47
|
+
|
|
48
|
+
def __eq__(self, other):
|
|
49
|
+
return isinstance(other, MemoryObject) and self.id == other.id
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class MemoryStats:
|
|
54
|
+
"""Memory statistics"""
|
|
55
|
+
total_allocated: int = 0
|
|
56
|
+
total_freed: int = 0
|
|
57
|
+
current_usage: int = 0
|
|
58
|
+
peak_usage: int = 0
|
|
59
|
+
allocation_count: int = 0
|
|
60
|
+
deallocation_count: int = 0
|
|
61
|
+
gc_runs: int = 0
|
|
62
|
+
gc_time: float = 0.0
|
|
63
|
+
objects_collected: int = 0
|
|
64
|
+
|
|
65
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
66
|
+
"""Convert to dictionary for reporting"""
|
|
67
|
+
return {
|
|
68
|
+
'total_allocated': f"{self.total_allocated:,} bytes",
|
|
69
|
+
'total_freed': f"{self.total_freed:,} bytes",
|
|
70
|
+
'current_usage': f"{self.current_usage:,} bytes",
|
|
71
|
+
'peak_usage': f"{self.peak_usage:,} bytes",
|
|
72
|
+
'allocation_count': self.allocation_count,
|
|
73
|
+
'deallocation_count': self.deallocation_count,
|
|
74
|
+
'gc_runs': self.gc_runs,
|
|
75
|
+
'gc_time': f"{self.gc_time:.4f}s",
|
|
76
|
+
'objects_collected': self.objects_collected,
|
|
77
|
+
'memory_efficiency': f"{(self.total_freed / max(self.total_allocated, 1)) * 100:.1f}%"
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class Heap:
|
|
82
|
+
"""Custom heap allocator for Zexus VM"""
|
|
83
|
+
|
|
84
|
+
def __init__(self, max_size: int = 100 * 1024 * 1024): # 100MB default
|
|
85
|
+
"""Initialize heap allocator.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
max_size: Maximum heap size in bytes
|
|
89
|
+
"""
|
|
90
|
+
self.max_size = max_size
|
|
91
|
+
self.objects: Dict[int, MemoryObject] = {}
|
|
92
|
+
self.free_list: List[int] = []
|
|
93
|
+
self.next_id = 0
|
|
94
|
+
self.stats = MemoryStats()
|
|
95
|
+
|
|
96
|
+
def allocate(self, obj: Any, size: Optional[int] = None) -> int:
|
|
97
|
+
"""Allocate memory for an object.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
obj: Object to allocate memory for
|
|
101
|
+
size: Size in bytes (None = auto-calculate)
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
Object ID
|
|
105
|
+
|
|
106
|
+
Raises:
|
|
107
|
+
MemoryError: If allocation would exceed max heap size
|
|
108
|
+
"""
|
|
109
|
+
if size is None:
|
|
110
|
+
size = sys.getsizeof(obj)
|
|
111
|
+
|
|
112
|
+
# Check heap limit
|
|
113
|
+
if self.stats.current_usage + size > self.max_size:
|
|
114
|
+
raise MemoryError(f"Heap full: {self.stats.current_usage + size} > {self.max_size}")
|
|
115
|
+
|
|
116
|
+
# Reuse freed ID if available
|
|
117
|
+
if self.free_list:
|
|
118
|
+
obj_id = self.free_list.pop()
|
|
119
|
+
else:
|
|
120
|
+
obj_id = self.next_id
|
|
121
|
+
self.next_id += 1
|
|
122
|
+
|
|
123
|
+
# Create memory object
|
|
124
|
+
mem_obj = MemoryObject(
|
|
125
|
+
id=obj_id,
|
|
126
|
+
obj=obj,
|
|
127
|
+
size=size,
|
|
128
|
+
allocated_at=time.time()
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
self.objects[obj_id] = mem_obj
|
|
132
|
+
|
|
133
|
+
# Update statistics
|
|
134
|
+
self.stats.total_allocated += size
|
|
135
|
+
self.stats.current_usage += size
|
|
136
|
+
self.stats.allocation_count += 1
|
|
137
|
+
|
|
138
|
+
if self.stats.current_usage > self.stats.peak_usage:
|
|
139
|
+
self.stats.peak_usage = self.stats.current_usage
|
|
140
|
+
|
|
141
|
+
return obj_id
|
|
142
|
+
|
|
143
|
+
def deallocate(self, obj_id: int) -> bool:
|
|
144
|
+
"""Deallocate memory for an object.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
obj_id: Object ID to deallocate
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
True if deallocated, False if not found
|
|
151
|
+
"""
|
|
152
|
+
if obj_id not in self.objects:
|
|
153
|
+
return False
|
|
154
|
+
|
|
155
|
+
mem_obj = self.objects[obj_id]
|
|
156
|
+
|
|
157
|
+
# Update statistics
|
|
158
|
+
self.stats.total_freed += mem_obj.size
|
|
159
|
+
self.stats.current_usage -= mem_obj.size
|
|
160
|
+
self.stats.deallocation_count += 1
|
|
161
|
+
|
|
162
|
+
# Remove object and add ID to free list
|
|
163
|
+
del self.objects[obj_id]
|
|
164
|
+
self.free_list.append(obj_id)
|
|
165
|
+
|
|
166
|
+
return True
|
|
167
|
+
|
|
168
|
+
def get_object(self, obj_id: int) -> Optional[Any]:
|
|
169
|
+
"""Get object by ID.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
obj_id: Object ID
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
Object or None if not found
|
|
176
|
+
"""
|
|
177
|
+
mem_obj = self.objects.get(obj_id)
|
|
178
|
+
return mem_obj.obj if mem_obj else None
|
|
179
|
+
|
|
180
|
+
def get_memory_object(self, obj_id: int) -> Optional[MemoryObject]:
|
|
181
|
+
"""Get memory object wrapper by ID.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
obj_id: Object ID
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
MemoryObject or None if not found
|
|
188
|
+
"""
|
|
189
|
+
return self.objects.get(obj_id)
|
|
190
|
+
|
|
191
|
+
def get_all_objects(self) -> List[MemoryObject]:
|
|
192
|
+
"""Get all allocated objects.
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
List of all memory objects
|
|
196
|
+
"""
|
|
197
|
+
return list(self.objects.values())
|
|
198
|
+
|
|
199
|
+
def reset_stats(self):
|
|
200
|
+
"""Reset statistics counters"""
|
|
201
|
+
self.stats = MemoryStats()
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class GarbageCollector:
|
|
205
|
+
"""Mark-and-sweep garbage collector"""
|
|
206
|
+
|
|
207
|
+
def __init__(self, heap: Heap, threshold: int = 1000):
|
|
208
|
+
"""Initialize garbage collector.
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
heap: Heap allocator to manage
|
|
212
|
+
threshold: Number of allocations before triggering GC
|
|
213
|
+
"""
|
|
214
|
+
self.heap = heap
|
|
215
|
+
self.threshold = threshold
|
|
216
|
+
self.allocations_since_gc = 0
|
|
217
|
+
self.root_set: Set[int] = set()
|
|
218
|
+
|
|
219
|
+
def add_root(self, obj_id: int):
|
|
220
|
+
"""Add object to root set (prevents collection).
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
obj_id: Object ID to add to roots
|
|
224
|
+
"""
|
|
225
|
+
self.root_set.add(obj_id)
|
|
226
|
+
|
|
227
|
+
def remove_root(self, obj_id: int):
|
|
228
|
+
"""Remove object from root set.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
obj_id: Object ID to remove from roots
|
|
232
|
+
"""
|
|
233
|
+
self.root_set.discard(obj_id)
|
|
234
|
+
|
|
235
|
+
def mark_phase(self) -> Set[int]:
|
|
236
|
+
"""Mark all reachable objects.
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
Set of reachable object IDs
|
|
240
|
+
"""
|
|
241
|
+
marked = set()
|
|
242
|
+
work_list = list(self.root_set)
|
|
243
|
+
|
|
244
|
+
while work_list:
|
|
245
|
+
obj_id = work_list.pop()
|
|
246
|
+
|
|
247
|
+
if obj_id in marked:
|
|
248
|
+
continue
|
|
249
|
+
|
|
250
|
+
marked.add(obj_id)
|
|
251
|
+
|
|
252
|
+
# Mark the object
|
|
253
|
+
mem_obj = self.heap.get_memory_object(obj_id)
|
|
254
|
+
if mem_obj:
|
|
255
|
+
mem_obj.state = ObjectState.MARKED
|
|
256
|
+
|
|
257
|
+
# Find references to other managed objects
|
|
258
|
+
# (In a real implementation, this would traverse object references)
|
|
259
|
+
# For now, we assume objects with higher ref_count are referenced
|
|
260
|
+
|
|
261
|
+
return marked
|
|
262
|
+
|
|
263
|
+
def sweep_phase(self, marked: Set[int]) -> int:
|
|
264
|
+
"""Sweep (collect) unmarked objects.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
marked: Set of marked object IDs
|
|
268
|
+
|
|
269
|
+
Returns:
|
|
270
|
+
Number of objects collected
|
|
271
|
+
"""
|
|
272
|
+
collected = 0
|
|
273
|
+
to_collect = []
|
|
274
|
+
|
|
275
|
+
# Find objects to collect
|
|
276
|
+
for obj_id, mem_obj in list(self.heap.objects.items()):
|
|
277
|
+
if obj_id not in marked and obj_id not in self.root_set:
|
|
278
|
+
to_collect.append(obj_id)
|
|
279
|
+
|
|
280
|
+
# Collect objects
|
|
281
|
+
for obj_id in to_collect:
|
|
282
|
+
self.heap.deallocate(obj_id)
|
|
283
|
+
collected += 1
|
|
284
|
+
|
|
285
|
+
# Reset state for remaining objects
|
|
286
|
+
for mem_obj in self.heap.get_all_objects():
|
|
287
|
+
mem_obj.state = ObjectState.ALLOCATED
|
|
288
|
+
|
|
289
|
+
return collected
|
|
290
|
+
|
|
291
|
+
def collect(self, force: bool = False) -> Tuple[int, float]:
|
|
292
|
+
"""Run garbage collection cycle.
|
|
293
|
+
|
|
294
|
+
Args:
|
|
295
|
+
force: Force collection even if threshold not reached
|
|
296
|
+
|
|
297
|
+
Returns:
|
|
298
|
+
Tuple of (objects_collected, gc_time)
|
|
299
|
+
"""
|
|
300
|
+
# Check if collection needed
|
|
301
|
+
if not force and self.allocations_since_gc < self.threshold:
|
|
302
|
+
return 0, 0.0
|
|
303
|
+
|
|
304
|
+
start_time = time.time()
|
|
305
|
+
|
|
306
|
+
# Mark phase
|
|
307
|
+
marked = self.mark_phase()
|
|
308
|
+
|
|
309
|
+
# Sweep phase
|
|
310
|
+
collected = self.sweep_phase(marked)
|
|
311
|
+
|
|
312
|
+
# Update statistics
|
|
313
|
+
gc_time = time.time() - start_time
|
|
314
|
+
self.heap.stats.gc_runs += 1
|
|
315
|
+
self.heap.stats.gc_time += gc_time
|
|
316
|
+
self.heap.stats.objects_collected += collected
|
|
317
|
+
|
|
318
|
+
# Reset allocation counter
|
|
319
|
+
self.allocations_since_gc = 0
|
|
320
|
+
|
|
321
|
+
return collected, gc_time
|
|
322
|
+
|
|
323
|
+
def should_collect(self) -> bool:
|
|
324
|
+
"""Check if garbage collection should run.
|
|
325
|
+
|
|
326
|
+
Returns:
|
|
327
|
+
True if GC should run
|
|
328
|
+
"""
|
|
329
|
+
return self.allocations_since_gc >= self.threshold
|
|
330
|
+
|
|
331
|
+
def record_allocation(self):
|
|
332
|
+
"""Record an allocation (for threshold tracking)"""
|
|
333
|
+
self.allocations_since_gc += 1
|
|
334
|
+
|
|
335
|
+
# Auto-trigger collection if threshold reached
|
|
336
|
+
if self.should_collect():
|
|
337
|
+
self.collect()
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
class MemoryManager:
|
|
341
|
+
"""Main memory manager for Zexus VM"""
|
|
342
|
+
|
|
343
|
+
def __init__(
|
|
344
|
+
self,
|
|
345
|
+
max_heap_size: int = 100 * 1024 * 1024,
|
|
346
|
+
gc_threshold: int = 1000,
|
|
347
|
+
enable_profiling: bool = True
|
|
348
|
+
):
|
|
349
|
+
"""Initialize memory manager.
|
|
350
|
+
|
|
351
|
+
Args:
|
|
352
|
+
max_heap_size: Maximum heap size in bytes
|
|
353
|
+
gc_threshold: Allocations before GC trigger
|
|
354
|
+
enable_profiling: Enable memory profiling
|
|
355
|
+
"""
|
|
356
|
+
self.heap = Heap(max_size=max_heap_size)
|
|
357
|
+
self.gc = GarbageCollector(heap=self.heap, threshold=gc_threshold)
|
|
358
|
+
self.enable_profiling = enable_profiling
|
|
359
|
+
self.allocation_history: List[Tuple[float, int, int]] = [] # (time, obj_id, size)
|
|
360
|
+
|
|
361
|
+
def allocate(self, obj: Any, root: bool = False) -> int:
|
|
362
|
+
"""Allocate memory for object.
|
|
363
|
+
|
|
364
|
+
Args:
|
|
365
|
+
obj: Object to allocate
|
|
366
|
+
root: If True, add to root set (prevent collection)
|
|
367
|
+
|
|
368
|
+
Returns:
|
|
369
|
+
Object ID
|
|
370
|
+
"""
|
|
371
|
+
obj_id = self.heap.allocate(obj)
|
|
372
|
+
|
|
373
|
+
if root:
|
|
374
|
+
self.gc.add_root(obj_id)
|
|
375
|
+
|
|
376
|
+
# Record allocation for profiling
|
|
377
|
+
if self.enable_profiling:
|
|
378
|
+
mem_obj = self.heap.get_memory_object(obj_id)
|
|
379
|
+
if mem_obj:
|
|
380
|
+
self.allocation_history.append((time.time(), obj_id, mem_obj.size))
|
|
381
|
+
|
|
382
|
+
# Record for GC
|
|
383
|
+
self.gc.record_allocation()
|
|
384
|
+
|
|
385
|
+
return obj_id
|
|
386
|
+
|
|
387
|
+
def deallocate(self, obj_id: int) -> bool:
|
|
388
|
+
"""Deallocate object.
|
|
389
|
+
|
|
390
|
+
Args:
|
|
391
|
+
obj_id: Object ID
|
|
392
|
+
|
|
393
|
+
Returns:
|
|
394
|
+
True if deallocated
|
|
395
|
+
"""
|
|
396
|
+
self.gc.remove_root(obj_id)
|
|
397
|
+
return self.heap.deallocate(obj_id)
|
|
398
|
+
|
|
399
|
+
def get(self, obj_id: int) -> Optional[Any]:
|
|
400
|
+
"""Get object by ID.
|
|
401
|
+
|
|
402
|
+
Args:
|
|
403
|
+
obj_id: Object ID
|
|
404
|
+
|
|
405
|
+
Returns:
|
|
406
|
+
Object or None
|
|
407
|
+
"""
|
|
408
|
+
return self.heap.get_object(obj_id)
|
|
409
|
+
|
|
410
|
+
def collect_garbage(self, force: bool = False) -> Tuple[int, float]:
|
|
411
|
+
"""Trigger garbage collection.
|
|
412
|
+
|
|
413
|
+
Args:
|
|
414
|
+
force: Force collection
|
|
415
|
+
|
|
416
|
+
Returns:
|
|
417
|
+
Tuple of (objects_collected, gc_time)
|
|
418
|
+
"""
|
|
419
|
+
return self.gc.collect(force=force)
|
|
420
|
+
|
|
421
|
+
def get_stats(self) -> Dict[str, Any]:
|
|
422
|
+
"""Get memory statistics.
|
|
423
|
+
|
|
424
|
+
Returns:
|
|
425
|
+
Statistics dictionary
|
|
426
|
+
"""
|
|
427
|
+
return self.heap.stats.to_dict()
|
|
428
|
+
|
|
429
|
+
def get_memory_report(self) -> str:
|
|
430
|
+
"""Generate detailed memory report.
|
|
431
|
+
|
|
432
|
+
Returns:
|
|
433
|
+
Formatted memory report
|
|
434
|
+
"""
|
|
435
|
+
stats = self.heap.stats
|
|
436
|
+
report = []
|
|
437
|
+
|
|
438
|
+
report.append("=" * 60)
|
|
439
|
+
report.append("Zexus Memory Manager Report")
|
|
440
|
+
report.append("=" * 60)
|
|
441
|
+
report.append("")
|
|
442
|
+
|
|
443
|
+
report.append("Memory Usage:")
|
|
444
|
+
report.append(f" Current: {stats.current_usage:,} bytes")
|
|
445
|
+
report.append(f" Peak: {stats.peak_usage:,} bytes")
|
|
446
|
+
report.append(f" Total Alloc: {stats.total_allocated:,} bytes")
|
|
447
|
+
report.append(f" Total Freed: {stats.total_freed:,} bytes")
|
|
448
|
+
report.append("")
|
|
449
|
+
|
|
450
|
+
report.append("Allocation Statistics:")
|
|
451
|
+
report.append(f" Allocations: {stats.allocation_count:,}")
|
|
452
|
+
report.append(f" Deallocations: {stats.deallocation_count:,}")
|
|
453
|
+
report.append(f" Live Objects: {len(self.heap.objects):,}")
|
|
454
|
+
report.append("")
|
|
455
|
+
|
|
456
|
+
report.append("Garbage Collection:")
|
|
457
|
+
report.append(f" GC Runs: {stats.gc_runs:,}")
|
|
458
|
+
report.append(f" GC Time: {stats.gc_time:.4f}s")
|
|
459
|
+
report.append(f" Collected: {stats.objects_collected:,} objects")
|
|
460
|
+
if stats.gc_runs > 0:
|
|
461
|
+
report.append(f" Avg GC Time: {stats.gc_time / stats.gc_runs:.4f}s")
|
|
462
|
+
report.append("")
|
|
463
|
+
|
|
464
|
+
efficiency = (stats.total_freed / max(stats.total_allocated, 1)) * 100
|
|
465
|
+
report.append(f"Memory Efficiency: {efficiency:.1f}%")
|
|
466
|
+
report.append("")
|
|
467
|
+
|
|
468
|
+
report.append("=" * 60)
|
|
469
|
+
|
|
470
|
+
return "\n".join(report)
|
|
471
|
+
|
|
472
|
+
def detect_leaks(self) -> List[MemoryObject]:
|
|
473
|
+
"""Detect potential memory leaks.
|
|
474
|
+
|
|
475
|
+
Returns:
|
|
476
|
+
List of objects that may be leaking
|
|
477
|
+
"""
|
|
478
|
+
current_time = time.time()
|
|
479
|
+
leak_threshold = 60.0 # Objects alive for 60+ seconds
|
|
480
|
+
|
|
481
|
+
potential_leaks = []
|
|
482
|
+
for mem_obj in self.heap.get_all_objects():
|
|
483
|
+
age = current_time - mem_obj.allocated_at
|
|
484
|
+
if age > leak_threshold and mem_obj.id not in self.gc.root_set:
|
|
485
|
+
potential_leaks.append(mem_obj)
|
|
486
|
+
|
|
487
|
+
return potential_leaks
|
|
488
|
+
|
|
489
|
+
def reset(self):
|
|
490
|
+
"""Reset memory manager (for testing)"""
|
|
491
|
+
self.heap = Heap(max_size=self.heap.max_size)
|
|
492
|
+
self.gc = GarbageCollector(heap=self.heap, threshold=self.gc.threshold)
|
|
493
|
+
self.allocation_history.clear()
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
# Convenience function for creating memory manager
|
|
497
|
+
def create_memory_manager(
|
|
498
|
+
max_heap_mb: int = 100,
|
|
499
|
+
gc_threshold: int = 1000
|
|
500
|
+
) -> MemoryManager:
|
|
501
|
+
"""Create a memory manager with common settings.
|
|
502
|
+
|
|
503
|
+
Args:
|
|
504
|
+
max_heap_mb: Maximum heap size in megabytes
|
|
505
|
+
gc_threshold: Allocations before GC trigger
|
|
506
|
+
|
|
507
|
+
Returns:
|
|
508
|
+
Configured MemoryManager
|
|
509
|
+
|
|
510
|
+
Example:
|
|
511
|
+
>>> mm = create_memory_manager(max_heap_mb=50, gc_threshold=500)
|
|
512
|
+
>>> obj_id = mm.allocate({"key": "value"})
|
|
513
|
+
>>> obj = mm.get(obj_id)
|
|
514
|
+
"""
|
|
515
|
+
max_heap_bytes = max_heap_mb * 1024 * 1024
|
|
516
|
+
return MemoryManager(
|
|
517
|
+
max_heap_size=max_heap_bytes,
|
|
518
|
+
gc_threshold=gc_threshold,
|
|
519
|
+
enable_profiling=True
|
|
520
|
+
)
|