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.
Files changed (227) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +2513 -0
  3. package/bin/zexus +2 -0
  4. package/bin/zpics +2 -0
  5. package/bin/zpm +2 -0
  6. package/bin/zx +2 -0
  7. package/bin/zx-deploy +2 -0
  8. package/bin/zx-dev +2 -0
  9. package/bin/zx-run +2 -0
  10. package/package.json +66 -0
  11. package/scripts/README.md +24 -0
  12. package/scripts/postinstall.js +44 -0
  13. package/shared_config.json +24 -0
  14. package/src/README.md +1525 -0
  15. package/src/tests/run_zexus_tests.py +117 -0
  16. package/src/tests/test_all_phases.zx +346 -0
  17. package/src/tests/test_blockchain_features.zx +306 -0
  18. package/src/tests/test_complexity_features.zx +321 -0
  19. package/src/tests/test_core_integration.py +185 -0
  20. package/src/tests/test_phase10_ecosystem.zx +177 -0
  21. package/src/tests/test_phase1_modifiers.zx +87 -0
  22. package/src/tests/test_phase2_plugins.zx +80 -0
  23. package/src/tests/test_phase3_security.zx +97 -0
  24. package/src/tests/test_phase4_vfs.zx +116 -0
  25. package/src/tests/test_phase5_types.zx +117 -0
  26. package/src/tests/test_phase6_metaprogramming.zx +125 -0
  27. package/src/tests/test_phase7_optimization.zx +132 -0
  28. package/src/tests/test_phase9_advanced_types.zx +157 -0
  29. package/src/tests/test_security_features.py +419 -0
  30. package/src/tests/test_security_features.zx +276 -0
  31. package/src/tests/test_simple_zx.zx +1 -0
  32. package/src/tests/test_verification_simple.zx +69 -0
  33. package/src/zexus/__init__.py +28 -0
  34. package/src/zexus/__main__.py +5 -0
  35. package/src/zexus/__pycache__/__init__.cpython-312.pyc +0 -0
  36. package/src/zexus/__pycache__/advanced_types.cpython-312.pyc +0 -0
  37. package/src/zexus/__pycache__/builtin_modules.cpython-312.pyc +0 -0
  38. package/src/zexus/__pycache__/capability_system.cpython-312.pyc +0 -0
  39. package/src/zexus/__pycache__/complexity_system.cpython-312.pyc +0 -0
  40. package/src/zexus/__pycache__/concurrency_system.cpython-312.pyc +0 -0
  41. package/src/zexus/__pycache__/config.cpython-312.pyc +0 -0
  42. package/src/zexus/__pycache__/dependency_injection.cpython-312.pyc +0 -0
  43. package/src/zexus/__pycache__/ecosystem.cpython-312.pyc +0 -0
  44. package/src/zexus/__pycache__/environment.cpython-312.pyc +0 -0
  45. package/src/zexus/__pycache__/error_reporter.cpython-312.pyc +0 -0
  46. package/src/zexus/__pycache__/hybrid_orchestrator.cpython-312.pyc +0 -0
  47. package/src/zexus/__pycache__/lexer.cpython-312.pyc +0 -0
  48. package/src/zexus/__pycache__/metaprogramming.cpython-312.pyc +0 -0
  49. package/src/zexus/__pycache__/module_cache.cpython-312.pyc +0 -0
  50. package/src/zexus/__pycache__/object.cpython-312.pyc +0 -0
  51. package/src/zexus/__pycache__/optimization.cpython-312.pyc +0 -0
  52. package/src/zexus/__pycache__/plugin_system.cpython-312.pyc +0 -0
  53. package/src/zexus/__pycache__/policy_engine.cpython-312.pyc +0 -0
  54. package/src/zexus/__pycache__/security.cpython-312.pyc +0 -0
  55. package/src/zexus/__pycache__/stdlib_integration.cpython-312.pyc +0 -0
  56. package/src/zexus/__pycache__/strategy_recovery.cpython-312.pyc +0 -0
  57. package/src/zexus/__pycache__/syntax_validator.cpython-312.pyc +0 -0
  58. package/src/zexus/__pycache__/type_system.cpython-312.pyc +0 -0
  59. package/src/zexus/__pycache__/virtual_filesystem.cpython-312.pyc +0 -0
  60. package/src/zexus/__pycache__/zexus_ast.cpython-312.pyc +0 -0
  61. package/src/zexus/__pycache__/zexus_token.cpython-312.pyc +0 -0
  62. package/src/zexus/advanced_types.py +401 -0
  63. package/src/zexus/blockchain/__init__.py +40 -0
  64. package/src/zexus/blockchain/__pycache__/__init__.cpython-312.pyc +0 -0
  65. package/src/zexus/blockchain/__pycache__/crypto.cpython-312.pyc +0 -0
  66. package/src/zexus/blockchain/__pycache__/ledger.cpython-312.pyc +0 -0
  67. package/src/zexus/blockchain/__pycache__/transaction.cpython-312.pyc +0 -0
  68. package/src/zexus/blockchain/crypto.py +463 -0
  69. package/src/zexus/blockchain/ledger.py +255 -0
  70. package/src/zexus/blockchain/transaction.py +267 -0
  71. package/src/zexus/builtin_modules.py +284 -0
  72. package/src/zexus/builtin_plugins.py +317 -0
  73. package/src/zexus/capability_system.py +372 -0
  74. package/src/zexus/cli/__init__.py +2 -0
  75. package/src/zexus/cli/__pycache__/__init__.cpython-312.pyc +0 -0
  76. package/src/zexus/cli/__pycache__/main.cpython-312.pyc +0 -0
  77. package/src/zexus/cli/main.py +707 -0
  78. package/src/zexus/cli/zpm.py +203 -0
  79. package/src/zexus/compare_interpreter_compiler.py +146 -0
  80. package/src/zexus/compiler/__init__.py +169 -0
  81. package/src/zexus/compiler/__pycache__/__init__.cpython-312.pyc +0 -0
  82. package/src/zexus/compiler/__pycache__/lexer.cpython-312.pyc +0 -0
  83. package/src/zexus/compiler/__pycache__/parser.cpython-312.pyc +0 -0
  84. package/src/zexus/compiler/__pycache__/zexus_ast.cpython-312.pyc +0 -0
  85. package/src/zexus/compiler/bytecode.py +266 -0
  86. package/src/zexus/compiler/compat_runtime.py +277 -0
  87. package/src/zexus/compiler/lexer.py +257 -0
  88. package/src/zexus/compiler/parser.py +779 -0
  89. package/src/zexus/compiler/semantic.py +118 -0
  90. package/src/zexus/compiler/zexus_ast.py +454 -0
  91. package/src/zexus/complexity_system.py +575 -0
  92. package/src/zexus/concurrency_system.py +493 -0
  93. package/src/zexus/config.py +201 -0
  94. package/src/zexus/crypto_bridge.py +19 -0
  95. package/src/zexus/dependency_injection.py +423 -0
  96. package/src/zexus/ecosystem.py +434 -0
  97. package/src/zexus/environment.py +101 -0
  98. package/src/zexus/environment_manager.py +119 -0
  99. package/src/zexus/error_reporter.py +314 -0
  100. package/src/zexus/evaluator/__init__.py +12 -0
  101. package/src/zexus/evaluator/__pycache__/__init__.cpython-312.pyc +0 -0
  102. package/src/zexus/evaluator/__pycache__/bytecode_compiler.cpython-312.pyc +0 -0
  103. package/src/zexus/evaluator/__pycache__/core.cpython-312.pyc +0 -0
  104. package/src/zexus/evaluator/__pycache__/expressions.cpython-312.pyc +0 -0
  105. package/src/zexus/evaluator/__pycache__/functions.cpython-312.pyc +0 -0
  106. package/src/zexus/evaluator/__pycache__/integration.cpython-312.pyc +0 -0
  107. package/src/zexus/evaluator/__pycache__/statements.cpython-312.pyc +0 -0
  108. package/src/zexus/evaluator/__pycache__/utils.cpython-312.pyc +0 -0
  109. package/src/zexus/evaluator/bytecode_compiler.py +700 -0
  110. package/src/zexus/evaluator/core.py +891 -0
  111. package/src/zexus/evaluator/expressions.py +827 -0
  112. package/src/zexus/evaluator/functions.py +3989 -0
  113. package/src/zexus/evaluator/integration.py +396 -0
  114. package/src/zexus/evaluator/statements.py +4303 -0
  115. package/src/zexus/evaluator/utils.py +126 -0
  116. package/src/zexus/evaluator_original.py +2041 -0
  117. package/src/zexus/external_bridge.py +16 -0
  118. package/src/zexus/find_affected_imports.sh +155 -0
  119. package/src/zexus/hybrid_orchestrator.py +152 -0
  120. package/src/zexus/input_validation.py +259 -0
  121. package/src/zexus/lexer.py +571 -0
  122. package/src/zexus/logging.py +89 -0
  123. package/src/zexus/lsp/__init__.py +9 -0
  124. package/src/zexus/lsp/completion_provider.py +207 -0
  125. package/src/zexus/lsp/definition_provider.py +22 -0
  126. package/src/zexus/lsp/hover_provider.py +71 -0
  127. package/src/zexus/lsp/server.py +269 -0
  128. package/src/zexus/lsp/symbol_provider.py +31 -0
  129. package/src/zexus/metaprogramming.py +321 -0
  130. package/src/zexus/module_cache.py +89 -0
  131. package/src/zexus/module_manager.py +107 -0
  132. package/src/zexus/object.py +973 -0
  133. package/src/zexus/optimization.py +424 -0
  134. package/src/zexus/parser/__init__.py +31 -0
  135. package/src/zexus/parser/__pycache__/__init__.cpython-312.pyc +0 -0
  136. package/src/zexus/parser/__pycache__/parser.cpython-312.pyc +0 -0
  137. package/src/zexus/parser/__pycache__/strategy_context.cpython-312.pyc +0 -0
  138. package/src/zexus/parser/__pycache__/strategy_structural.cpython-312.pyc +0 -0
  139. package/src/zexus/parser/integration.py +86 -0
  140. package/src/zexus/parser/parser.py +3977 -0
  141. package/src/zexus/parser/strategy_context.py +7254 -0
  142. package/src/zexus/parser/strategy_structural.py +1033 -0
  143. package/src/zexus/persistence.py +391 -0
  144. package/src/zexus/plugin_system.py +290 -0
  145. package/src/zexus/policy_engine.py +365 -0
  146. package/src/zexus/profiler/__init__.py +5 -0
  147. package/src/zexus/profiler/profiler.py +233 -0
  148. package/src/zexus/purity_system.py +398 -0
  149. package/src/zexus/runtime/__init__.py +20 -0
  150. package/src/zexus/runtime/async_runtime.py +324 -0
  151. package/src/zexus/search_old_imports.sh +65 -0
  152. package/src/zexus/security.py +1407 -0
  153. package/src/zexus/stack_trace.py +233 -0
  154. package/src/zexus/stdlib/__init__.py +27 -0
  155. package/src/zexus/stdlib/blockchain.py +341 -0
  156. package/src/zexus/stdlib/compression.py +167 -0
  157. package/src/zexus/stdlib/crypto.py +124 -0
  158. package/src/zexus/stdlib/datetime.py +163 -0
  159. package/src/zexus/stdlib/db_mongo.py +199 -0
  160. package/src/zexus/stdlib/db_mysql.py +162 -0
  161. package/src/zexus/stdlib/db_postgres.py +163 -0
  162. package/src/zexus/stdlib/db_sqlite.py +133 -0
  163. package/src/zexus/stdlib/encoding.py +230 -0
  164. package/src/zexus/stdlib/fs.py +195 -0
  165. package/src/zexus/stdlib/http.py +219 -0
  166. package/src/zexus/stdlib/http_server.py +248 -0
  167. package/src/zexus/stdlib/json_module.py +61 -0
  168. package/src/zexus/stdlib/math.py +360 -0
  169. package/src/zexus/stdlib/os_module.py +265 -0
  170. package/src/zexus/stdlib/regex.py +148 -0
  171. package/src/zexus/stdlib/sockets.py +253 -0
  172. package/src/zexus/stdlib/test_framework.zx +208 -0
  173. package/src/zexus/stdlib/test_runner.zx +119 -0
  174. package/src/zexus/stdlib_integration.py +341 -0
  175. package/src/zexus/strategy_recovery.py +256 -0
  176. package/src/zexus/syntax_validator.py +356 -0
  177. package/src/zexus/testing/zpics.py +407 -0
  178. package/src/zexus/testing/zpics_runtime.py +369 -0
  179. package/src/zexus/type_system.py +374 -0
  180. package/src/zexus/validation_system.py +569 -0
  181. package/src/zexus/virtual_filesystem.py +355 -0
  182. package/src/zexus/vm/__init__.py +8 -0
  183. package/src/zexus/vm/__pycache__/__init__.cpython-312.pyc +0 -0
  184. package/src/zexus/vm/__pycache__/async_optimizer.cpython-312.pyc +0 -0
  185. package/src/zexus/vm/__pycache__/bytecode.cpython-312.pyc +0 -0
  186. package/src/zexus/vm/__pycache__/cache.cpython-312.pyc +0 -0
  187. package/src/zexus/vm/__pycache__/jit.cpython-312.pyc +0 -0
  188. package/src/zexus/vm/__pycache__/memory_manager.cpython-312.pyc +0 -0
  189. package/src/zexus/vm/__pycache__/memory_pool.cpython-312.pyc +0 -0
  190. package/src/zexus/vm/__pycache__/optimizer.cpython-312.pyc +0 -0
  191. package/src/zexus/vm/__pycache__/parallel_vm.cpython-312.pyc +0 -0
  192. package/src/zexus/vm/__pycache__/peephole_optimizer.cpython-312.pyc +0 -0
  193. package/src/zexus/vm/__pycache__/profiler.cpython-312.pyc +0 -0
  194. package/src/zexus/vm/__pycache__/register_allocator.cpython-312.pyc +0 -0
  195. package/src/zexus/vm/__pycache__/register_vm.cpython-312.pyc +0 -0
  196. package/src/zexus/vm/__pycache__/ssa_converter.cpython-312.pyc +0 -0
  197. package/src/zexus/vm/__pycache__/vm.cpython-312.pyc +0 -0
  198. package/src/zexus/vm/async_optimizer.py +420 -0
  199. package/src/zexus/vm/bytecode.py +428 -0
  200. package/src/zexus/vm/bytecode_converter.py +297 -0
  201. package/src/zexus/vm/cache.py +532 -0
  202. package/src/zexus/vm/jit.py +720 -0
  203. package/src/zexus/vm/memory_manager.py +520 -0
  204. package/src/zexus/vm/memory_pool.py +511 -0
  205. package/src/zexus/vm/optimizer.py +478 -0
  206. package/src/zexus/vm/parallel_vm.py +899 -0
  207. package/src/zexus/vm/peephole_optimizer.py +452 -0
  208. package/src/zexus/vm/profiler.py +527 -0
  209. package/src/zexus/vm/register_allocator.py +462 -0
  210. package/src/zexus/vm/register_vm.py +520 -0
  211. package/src/zexus/vm/ssa_converter.py +757 -0
  212. package/src/zexus/vm/vm.py +1392 -0
  213. package/src/zexus/zexus_ast.py +1782 -0
  214. package/src/zexus/zexus_token.py +253 -0
  215. package/src/zexus/zpm/__init__.py +15 -0
  216. package/src/zexus/zpm/installer.py +116 -0
  217. package/src/zexus/zpm/package_manager.py +208 -0
  218. package/src/zexus/zpm/publisher.py +98 -0
  219. package/src/zexus/zpm/registry.py +110 -0
  220. package/src/zexus.egg-info/PKG-INFO +2235 -0
  221. package/src/zexus.egg-info/SOURCES.txt +876 -0
  222. package/src/zexus.egg-info/dependency_links.txt +1 -0
  223. package/src/zexus.egg-info/entry_points.txt +3 -0
  224. package/src/zexus.egg-info/not-zip-safe +1 -0
  225. package/src/zexus.egg-info/requires.txt +14 -0
  226. package/src/zexus.egg-info/top_level.txt +2 -0
  227. package/zexus.json +14 -0
@@ -0,0 +1,527 @@
1
+ """
2
+ Instruction-Level Profiler for Zexus VM
3
+
4
+ Provides detailed execution profiling including:
5
+ - Per-instruction execution counts
6
+ - Timing statistics (min/max/avg/p95/p99)
7
+ - Hot loop detection
8
+ - Memory access patterns
9
+ - Branch prediction analysis
10
+ """
11
+
12
+ import time
13
+ import json
14
+ from typing import Dict, List, Any, Optional, Tuple, Set
15
+ from dataclasses import dataclass, field
16
+ from collections import defaultdict, Counter
17
+ from enum import Enum
18
+
19
+
20
+ class ProfilingLevel(Enum):
21
+ """Profiling detail levels"""
22
+ NONE = 0 # No profiling
23
+ BASIC = 1 # Count only
24
+ DETAILED = 2 # Count + timing
25
+ FULL = 3 # Count + timing + memory + branches
26
+
27
+
28
+ @dataclass
29
+ class InstructionStats:
30
+ """Statistics for a single instruction"""
31
+ opcode: str
32
+ operand: Any
33
+ ip: int
34
+
35
+ # Execution statistics
36
+ count: int = 0
37
+ total_time: float = 0.0
38
+ min_time: float = float('inf')
39
+ max_time: float = 0.0
40
+
41
+ # Timing samples (for percentile calculation)
42
+ timing_samples: List[float] = field(default_factory=list)
43
+
44
+ # Memory tracking
45
+ memory_reads: int = 0
46
+ memory_writes: int = 0
47
+
48
+ # Branch tracking (for jumps)
49
+ branch_taken: int = 0
50
+ branch_not_taken: int = 0
51
+
52
+ def record_execution(self, execution_time: float = 0.0, increment_count: bool = True):
53
+ """Record a single execution"""
54
+ if increment_count:
55
+ self.count += 1
56
+ if execution_time > 0:
57
+ self.total_time += execution_time
58
+ self.min_time = min(self.min_time, execution_time)
59
+ self.max_time = max(self.max_time, execution_time)
60
+ self.timing_samples.append(execution_time)
61
+
62
+ # Keep sample size manageable (max 10000 samples)
63
+ if len(self.timing_samples) > 10000:
64
+ # Keep percentiles and random samples
65
+ self.timing_samples = sorted(self.timing_samples)
66
+ keep = [self.timing_samples[i] for i in
67
+ [0, len(self.timing_samples)//4, len(self.timing_samples)//2,
68
+ 3*len(self.timing_samples)//4, -1]]
69
+ self.timing_samples = keep
70
+
71
+ def avg_time(self) -> float:
72
+ """Average execution time"""
73
+ return self.total_time / self.count if self.count > 0 else 0.0
74
+
75
+ def percentile(self, p: int) -> float:
76
+ """Calculate percentile (0-100)"""
77
+ if not self.timing_samples:
78
+ return 0.0
79
+ sorted_samples = sorted(self.timing_samples)
80
+ idx = int(len(sorted_samples) * p / 100)
81
+ idx = min(idx, len(sorted_samples) - 1)
82
+ return sorted_samples[idx]
83
+
84
+ def to_dict(self) -> Dict[str, Any]:
85
+ """Convert to dictionary for serialization"""
86
+ return {
87
+ 'opcode': self.opcode,
88
+ 'operand': str(self.operand),
89
+ 'ip': self.ip,
90
+ 'count': self.count,
91
+ 'total_time_ms': self.total_time * 1000,
92
+ 'avg_time_us': self.avg_time() * 1_000_000,
93
+ 'min_time_us': self.min_time * 1_000_000 if self.min_time != float('inf') else 0,
94
+ 'max_time_us': self.max_time * 1_000_000,
95
+ 'p50_us': self.percentile(50) * 1_000_000,
96
+ 'p95_us': self.percentile(95) * 1_000_000,
97
+ 'p99_us': self.percentile(99) * 1_000_000,
98
+ 'memory_reads': self.memory_reads,
99
+ 'memory_writes': self.memory_writes,
100
+ 'branch_taken': self.branch_taken,
101
+ 'branch_not_taken': self.branch_not_taken,
102
+ 'branch_prediction_rate': self._branch_prediction_rate()
103
+ }
104
+
105
+ def _branch_prediction_rate(self) -> float:
106
+ """Calculate branch prediction success rate (always taken heuristic)"""
107
+ total = self.branch_taken + self.branch_not_taken
108
+ if total == 0:
109
+ return 0.0
110
+ # Simple heuristic: predict always taken
111
+ return (self.branch_taken / total) * 100
112
+
113
+
114
+ @dataclass
115
+ class HotLoop:
116
+ """Detected hot loop"""
117
+ start_ip: int
118
+ end_ip: int
119
+ iterations: int
120
+ total_time: float = 0.0
121
+ instructions: List[str] = field(default_factory=list)
122
+
123
+ def to_dict(self) -> Dict[str, Any]:
124
+ return {
125
+ 'start_ip': self.start_ip,
126
+ 'end_ip': self.end_ip,
127
+ 'iterations': self.iterations,
128
+ 'total_time_ms': self.total_time * 1000,
129
+ 'avg_iteration_us': (self.total_time / self.iterations * 1_000_000) if self.iterations > 0 else 0,
130
+ 'instruction_count': len(self.instructions),
131
+ 'instructions': self.instructions[:10] # First 10 instructions
132
+ }
133
+
134
+
135
+ class InstructionProfiler:
136
+ """
137
+ Profiler for VM instruction execution
138
+
139
+ Tracks execution statistics at instruction level with minimal overhead.
140
+ """
141
+
142
+ def __init__(self, level: ProfilingLevel = ProfilingLevel.DETAILED):
143
+ self.level = level
144
+ self.enabled = level != ProfilingLevel.NONE
145
+
146
+ # Per-instruction statistics (keyed by instruction pointer)
147
+ self.stats: Dict[int, InstructionStats] = {}
148
+
149
+ # Opcode frequency counter
150
+ self.opcode_counter: Counter = Counter()
151
+
152
+ # Hot loop detection
153
+ self.loops: List[HotLoop] = []
154
+ self._backward_jumps: Dict[Tuple[int, int], int] = defaultdict(int) # (from_ip, to_ip) -> count
155
+ self._loop_start_times: Dict[Tuple[int, int], float] = {}
156
+
157
+ # Global statistics
158
+ self.total_instructions: int = 0
159
+ self.profiling_overhead: float = 0.0
160
+ self.start_time: Optional[float] = None
161
+ self.end_time: Optional[float] = None
162
+
163
+ # Memory access tracking
164
+ self.memory_operations: Set[str] = {
165
+ 'LOAD_NAME', 'STORE_NAME', 'LOAD_CONST', 'LOAD_ATTR', 'STORE_ATTR',
166
+ 'LOAD_INDEX', 'STORE_INDEX', 'STATE_READ', 'STATE_WRITE'
167
+ }
168
+
169
+ # Branch instructions
170
+ self.branch_operations: Set[str] = {
171
+ 'JUMP', 'JUMP_IF_FALSE', 'JUMP_IF_TRUE', 'JUMP_FORWARD', 'JUMP_BACKWARD'
172
+ }
173
+
174
+ def start(self):
175
+ """Start profiling session"""
176
+ self.start_time = time.perf_counter()
177
+ self.enabled = True
178
+
179
+ def stop(self):
180
+ """Stop profiling session"""
181
+ self.end_time = time.perf_counter()
182
+ self.enabled = False
183
+
184
+ def reset(self):
185
+ """Reset all profiling data"""
186
+ self.stats.clear()
187
+ self.opcode_counter.clear()
188
+ self.loops.clear()
189
+ self._backward_jumps.clear()
190
+ self._loop_start_times.clear()
191
+ self.total_instructions = 0
192
+ self.profiling_overhead = 0.0
193
+ self.start_time = None
194
+ self.end_time = None
195
+
196
+ def record_instruction(
197
+ self,
198
+ ip: int,
199
+ opcode: str,
200
+ operand: Any,
201
+ prev_ip: Optional[int] = None,
202
+ stack_size: int = 0
203
+ ):
204
+ """
205
+ Record execution of an instruction
206
+
207
+ Args:
208
+ ip: Instruction pointer
209
+ opcode: Operation code
210
+ operand: Operand value
211
+ prev_ip: Previous instruction pointer (for jump detection)
212
+ stack_size: Current stack size
213
+ """
214
+ if not self.enabled:
215
+ return
216
+
217
+ overhead_start = time.perf_counter()
218
+
219
+ # Update counters
220
+ self.total_instructions += 1
221
+ self.opcode_counter[opcode] += 1
222
+
223
+ # Get or create stats for this instruction
224
+ if ip not in self.stats:
225
+ self.stats[ip] = InstructionStats(opcode=opcode, operand=operand, ip=ip)
226
+
227
+ stat = self.stats[ip]
228
+
229
+ # Only increment count (timing done separately by measure_instruction)
230
+ stat.count += 1
231
+
232
+ # Track memory operations (FULL level only)
233
+ if self.level == ProfilingLevel.FULL:
234
+ if opcode in self.memory_operations:
235
+ if opcode in ('LOAD_NAME', 'LOAD_CONST', 'LOAD_ATTR', 'LOAD_INDEX', 'STATE_READ'):
236
+ stat.memory_reads += 1
237
+ else:
238
+ stat.memory_writes += 1
239
+
240
+ # Track branches and detect hot loops
241
+ if prev_ip is not None and opcode in self.branch_operations:
242
+ # Detect backward jump (potential loop)
243
+ if ip < prev_ip:
244
+ jump_key = (prev_ip, ip)
245
+ self._backward_jumps[jump_key] += 1
246
+
247
+ # Hot loop threshold: >1000 iterations
248
+ if self._backward_jumps[jump_key] == 1:
249
+ self._loop_start_times[jump_key] = time.perf_counter()
250
+ elif self._backward_jumps[jump_key] % 1000 == 0:
251
+ # Record as hot loop
252
+ loop_time = time.perf_counter() - self._loop_start_times.get(jump_key, 0)
253
+ instructions = [self.stats[i].opcode for i in range(ip, prev_ip + 1) if i in self.stats]
254
+ loop = HotLoop(
255
+ start_ip=ip,
256
+ end_ip=prev_ip,
257
+ iterations=self._backward_jumps[jump_key],
258
+ total_time=loop_time,
259
+ instructions=instructions
260
+ )
261
+ # Update or add loop
262
+ existing = next((l for l in self.loops if l.start_ip == ip and l.end_ip == prev_ip), None)
263
+ if existing:
264
+ existing.iterations = loop.iterations
265
+ existing.total_time = loop_time
266
+ else:
267
+ self.loops.append(loop)
268
+
269
+ stat.branch_taken += 1
270
+ else:
271
+ stat.branch_not_taken += 1
272
+
273
+ # Minimal overhead tracking for non-FULL levels
274
+ self.profiling_overhead += (time.perf_counter() - overhead_start)
275
+
276
+ def measure_instruction(self, ip: int, execution_time: float):
277
+ """
278
+ Record execution time for an instruction
279
+
280
+ Args:
281
+ ip: Instruction pointer
282
+ execution_time: Time taken to execute (seconds)
283
+ """
284
+ if not self.enabled or self.level == ProfilingLevel.BASIC:
285
+ return
286
+
287
+ if ip in self.stats:
288
+ overhead_start = time.perf_counter()
289
+ # Don't increment count - that was already done by record_instruction
290
+ self.stats[ip].record_execution(execution_time, increment_count=False)
291
+ self.profiling_overhead += (time.perf_counter() - overhead_start)
292
+
293
+ def get_hottest_instructions(self, top_n: int = 10) -> List[InstructionStats]:
294
+ """Get top N hottest instructions by execution count"""
295
+ return sorted(self.stats.values(), key=lambda s: s.count, reverse=True)[:top_n]
296
+
297
+ def get_slowest_instructions(self, top_n: int = 10) -> List[InstructionStats]:
298
+ """Get top N slowest instructions by total time"""
299
+ return sorted(self.stats.values(), key=lambda s: s.total_time, reverse=True)[:top_n]
300
+
301
+ def get_hot_loops(self, min_iterations: int = 1000) -> List[HotLoop]:
302
+ """Get hot loops (loops executed many times)"""
303
+ return [loop for loop in self.loops if loop.iterations >= min_iterations]
304
+
305
+ def get_summary(self) -> Dict[str, Any]:
306
+ """Get profiling summary statistics"""
307
+ if not self.stats:
308
+ return {
309
+ 'profiling_level': self.level.name,
310
+ 'total_instructions': 0,
311
+ 'unique_instructions': 0,
312
+ 'total_time_sec': 0,
313
+ 'instructions_per_sec': 0,
314
+ 'profiling_overhead_ms': 0,
315
+ 'overhead_percentage': 0,
316
+ 'hot_loops_detected': 0,
317
+ 'most_common_opcodes': {}
318
+ }
319
+
320
+ total_time = (self.end_time or time.perf_counter()) - (self.start_time or 0)
321
+
322
+ return {
323
+ 'profiling_level': self.level.name,
324
+ 'total_instructions': self.total_instructions,
325
+ 'unique_instructions': len(self.stats),
326
+ 'total_time_sec': total_time,
327
+ 'instructions_per_sec': self.total_instructions / total_time if total_time > 0 else 0,
328
+ 'profiling_overhead_ms': self.profiling_overhead * 1000,
329
+ 'overhead_percentage': (self.profiling_overhead / total_time * 100) if total_time > 0 else 0,
330
+ 'hot_loops_detected': len(self.loops),
331
+ 'most_common_opcodes': dict(self.opcode_counter.most_common(10))
332
+ }
333
+
334
+ def generate_report(self, format: str = 'text', top_n: int = 20) -> str:
335
+ """
336
+ Generate profiling report
337
+
338
+ Args:
339
+ format: Output format ('text', 'json', 'html')
340
+ top_n: Number of top items to include
341
+
342
+ Returns:
343
+ Formatted report string
344
+ """
345
+ if format == 'json':
346
+ return self._generate_json_report(top_n)
347
+ elif format == 'html':
348
+ return self._generate_html_report(top_n)
349
+ else:
350
+ return self._generate_text_report(top_n)
351
+
352
+ def _generate_text_report(self, top_n: int) -> str:
353
+ """Generate text format report"""
354
+ summary = self.get_summary()
355
+ hottest = self.get_hottest_instructions(top_n)
356
+ slowest = self.get_slowest_instructions(top_n)
357
+ hot_loops = self.get_hot_loops()
358
+
359
+ lines = [
360
+ "=" * 80,
361
+ "ZEXUS VM INSTRUCTION PROFILING REPORT",
362
+ "=" * 80,
363
+ "",
364
+ "SUMMARY",
365
+ "-" * 80,
366
+ f"Profiling Level: {summary['profiling_level']}",
367
+ f"Total Instructions: {summary['total_instructions']:,}",
368
+ f"Unique Instructions: {summary['unique_instructions']:,}",
369
+ f"Total Time: {summary['total_time_sec']:.4f} seconds",
370
+ f"Instructions/Second: {summary['instructions_per_sec']:,.0f}",
371
+ f"Profiling Overhead: {summary['overhead_percentage']:.2f}% ({summary['profiling_overhead_ms']:.2f}ms)",
372
+ f"Hot Loops Detected: {summary['hot_loops_detected']}",
373
+ "",
374
+ "MOST COMMON OPCODES",
375
+ "-" * 80,
376
+ ]
377
+
378
+ for opcode, count in summary['most_common_opcodes'].items():
379
+ pct = (count / summary['total_instructions'] * 100) if summary['total_instructions'] > 0 else 0
380
+ lines.append(f" {opcode:20} {count:10,} ({pct:5.1f}%)")
381
+
382
+ lines.extend([
383
+ "",
384
+ f"TOP {top_n} HOTTEST INSTRUCTIONS (by count)",
385
+ "-" * 80,
386
+ f"{'IP':>6} {'Opcode':20} {'Count':>12} {'Avg (μs)':>12} {'Total (ms)':>12}",
387
+ "-" * 80,
388
+ ])
389
+
390
+ for stat in hottest:
391
+ lines.append(
392
+ f"{stat.ip:6} {stat.opcode:20} {stat.count:12,} "
393
+ f"{stat.avg_time() * 1_000_000:12.2f} {stat.total_time * 1000:12.2f}"
394
+ )
395
+
396
+ if self.level in (ProfilingLevel.DETAILED, ProfilingLevel.FULL):
397
+ lines.extend([
398
+ "",
399
+ f"TOP {top_n} SLOWEST INSTRUCTIONS (by total time)",
400
+ "-" * 80,
401
+ f"{'IP':>6} {'Opcode':20} {'Total (ms)':>12} {'Count':>12} {'Avg (μs)':>12}",
402
+ "-" * 80,
403
+ ])
404
+
405
+ for stat in slowest:
406
+ lines.append(
407
+ f"{stat.ip:6} {stat.opcode:20} {stat.total_time * 1000:12.2f} "
408
+ f"{stat.count:12,} {stat.avg_time() * 1_000_000:12.2f}"
409
+ )
410
+
411
+ if hot_loops:
412
+ lines.extend([
413
+ "",
414
+ "HOT LOOPS (>1000 iterations)",
415
+ "-" * 80,
416
+ f"{'Start':>6} {'End':>6} {'Iterations':>12} {'Total (ms)':>12} {'Avg/iter (μs)':>15}",
417
+ "-" * 80,
418
+ ])
419
+
420
+ for loop in sorted(hot_loops, key=lambda l: l.iterations, reverse=True):
421
+ avg_iter = (loop.total_time / loop.iterations * 1_000_000) if loop.iterations > 0 else 0
422
+ lines.append(
423
+ f"{loop.start_ip:6} {loop.end_ip:6} {loop.iterations:12,} "
424
+ f"{loop.total_time * 1000:12.2f} {avg_iter:15.2f}"
425
+ )
426
+
427
+ lines.extend([
428
+ "",
429
+ "=" * 80,
430
+ ])
431
+
432
+ return "\n".join(lines)
433
+
434
+ def _generate_json_report(self, top_n: int) -> str:
435
+ """Generate JSON format report"""
436
+ return json.dumps({
437
+ 'summary': self.get_summary(),
438
+ 'hottest_instructions': [s.to_dict() for s in self.get_hottest_instructions(top_n)],
439
+ 'slowest_instructions': [s.to_dict() for s in self.get_slowest_instructions(top_n)],
440
+ 'hot_loops': [l.to_dict() for l in self.get_hot_loops()],
441
+ 'opcode_distribution': dict(self.opcode_counter)
442
+ }, indent=2)
443
+
444
+ def _generate_html_report(self, top_n: int) -> str:
445
+ """Generate HTML format report"""
446
+ summary = self.get_summary()
447
+
448
+ html = f"""
449
+ <!DOCTYPE html>
450
+ <html>
451
+ <head>
452
+ <title>Zexus VM Profiling Report</title>
453
+ <style>
454
+ body {{ font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }}
455
+ .container {{ max-width: 1200px; margin: 0 auto; background: white; padding: 20px; box-shadow: 0 0 10px rgba(0,0,0,0.1); }}
456
+ h1 {{ color: #333; border-bottom: 3px solid #4CAF50; padding-bottom: 10px; }}
457
+ h2 {{ color: #555; margin-top: 30px; border-bottom: 2px solid #ddd; padding-bottom: 5px; }}
458
+ table {{ width: 100%; border-collapse: collapse; margin: 20px 0; }}
459
+ th, td {{ padding: 10px; text-align: left; border-bottom: 1px solid #ddd; }}
460
+ th {{ background: #4CAF50; color: white; }}
461
+ tr:hover {{ background: #f5f5f5; }}
462
+ .summary {{ display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin: 20px 0; }}
463
+ .summary-item {{ background: #f9f9f9; padding: 15px; border-left: 4px solid #4CAF50; }}
464
+ .summary-item strong {{ display: block; color: #333; margin-bottom: 5px; }}
465
+ </style>
466
+ </head>
467
+ <body>
468
+ <div class="container">
469
+ <h1>🔍 Zexus VM Instruction Profiling Report</h1>
470
+
471
+ <h2>Summary</h2>
472
+ <div class="summary">
473
+ <div class="summary-item">
474
+ <strong>Total Instructions</strong>
475
+ {summary['total_instructions']:,}
476
+ </div>
477
+ <div class="summary-item">
478
+ <strong>Unique Instructions</strong>
479
+ {summary['unique_instructions']:,}
480
+ </div>
481
+ <div class="summary-item">
482
+ <strong>Total Time</strong>
483
+ {summary['total_time_sec']:.4f} seconds
484
+ </div>
485
+ <div class="summary-item">
486
+ <strong>Instructions/Second</strong>
487
+ {summary['instructions_per_sec']:,.0f}
488
+ </div>
489
+ <div class="summary-item">
490
+ <strong>Profiling Overhead</strong>
491
+ {summary['overhead_percentage']:.2f}%
492
+ </div>
493
+ <div class="summary-item">
494
+ <strong>Hot Loops Detected</strong>
495
+ {summary['hot_loops_detected']}
496
+ </div>
497
+ </div>
498
+
499
+ <h2>Top {top_n} Hottest Instructions</h2>
500
+ <table>
501
+ <tr>
502
+ <th>IP</th>
503
+ <th>Opcode</th>
504
+ <th>Count</th>
505
+ <th>Avg (μs)</th>
506
+ <th>Total (ms)</th>
507
+ </tr>
508
+ """
509
+
510
+ for stat in self.get_hottest_instructions(top_n):
511
+ html += f"""
512
+ <tr>
513
+ <td>{stat.ip}</td>
514
+ <td>{stat.opcode}</td>
515
+ <td>{stat.count:,}</td>
516
+ <td>{stat.avg_time() * 1_000_000:.2f}</td>
517
+ <td>{stat.total_time * 1000:.2f}</td>
518
+ </tr>
519
+ """
520
+
521
+ html += """
522
+ </table>
523
+ </div>
524
+ </body>
525
+ </html>
526
+ """
527
+ return html