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,720 @@
1
+ """
2
+ Just-In-Time Compiler for Zexus VM
3
+
4
+ Provides tiered compilation:
5
+ - Tier 0: Interpreted execution (slowest, most flexible)
6
+ - Tier 1: Bytecode VM execution (fast, portable)
7
+ - Tier 2: JIT-compiled native code (fastest, hot paths only)
8
+
9
+ Features:
10
+ - Hot path detection via execution counters
11
+ - Bytecode optimization passes (via BytecodeOptimizer)
12
+ - Native code generation via Python compile()
13
+ - JIT cache for compiled code
14
+ - Automatic tier promotion
15
+ - Stack state simulation for accurate Python code generation
16
+ """
17
+
18
+ import hashlib
19
+ import time
20
+ import dis
21
+ from typing import Dict, Any, Optional, Tuple, Callable, List, Set
22
+ from dataclasses import dataclass, field
23
+ from enum import Enum
24
+
25
+ # Import optimizer for advanced optimization
26
+ try:
27
+ from .optimizer import BytecodeOptimizer
28
+ OPTIMIZER_AVAILABLE = True
29
+ except ImportError:
30
+ OPTIMIZER_AVAILABLE = False
31
+
32
+
33
+ class ExecutionTier(Enum):
34
+ """Execution tiers for tiered compilation"""
35
+ INTERPRETED = 0 # AST interpretation (slowest)
36
+ BYTECODE = 1 # Stack-based VM (fast)
37
+ JIT_NATIVE = 2 # JIT-compiled native code (fastest)
38
+
39
+
40
+ @dataclass
41
+ class HotPathInfo:
42
+ """Information about a hot execution path"""
43
+ bytecode_hash: str
44
+ execution_count: int = 0
45
+ total_time: float = 0.0
46
+ average_time: float = 0.0
47
+ last_execution: float = 0.0
48
+ compiled_version: Optional[Callable] = None
49
+ compilation_time: float = 0.0
50
+ tier: ExecutionTier = ExecutionTier.BYTECODE
51
+ speedup_factor: float = 1.0
52
+
53
+
54
+ @dataclass
55
+ class JITStats:
56
+ """JIT compilation statistics"""
57
+ hot_paths_detected: int = 0
58
+ compilations: int = 0
59
+ compilation_time: float = 0.0
60
+ average_compilation_time: float = 0.0
61
+ jit_executions: int = 0
62
+ total_jit_execution_time: float = 0.0
63
+ total_bytecode_execution_time: float = 0.0
64
+ cache_hits: int = 0
65
+ cache_misses: int = 0
66
+ tier_promotions: int = 0
67
+ compilation_failures: int = 0
68
+
69
+
70
+ @dataclass
71
+ class StackFrame:
72
+ """Represents stack state at a point in bytecode"""
73
+ stack: List[str] = field(default_factory=list) # Variable names on stack
74
+ variables: Dict[str, str] = field(default_factory=dict) # Variable -> expression
75
+ constants: Dict[int, Any] = field(default_factory=dict) # Constant ID -> value
76
+
77
+
78
+ class JITCompiler:
79
+ """
80
+ Just-In-Time compiler for Zexus VM bytecode
81
+
82
+ Implements a tiered compilation strategy:
83
+ 1. Detect hot paths via execution counting
84
+ 2. Optimize bytecode with peephole passes
85
+ 3. Compile to native Python code for maximum speed
86
+ 4. Cache compiled code for reuse
87
+ """
88
+
89
+ def __init__(self, hot_threshold: int = 100, optimization_level: int = 1, debug: bool = False):
90
+ """
91
+ Initialize JIT compiler
92
+
93
+ Args:
94
+ hot_threshold: Number of executions before JIT compilation
95
+ optimization_level: 0=none, 1=basic (default), 2=aggressive, 3=experimental
96
+ debug: Enable debug output
97
+ """
98
+ self.hot_threshold = hot_threshold
99
+ self.optimization_level = optimization_level
100
+ self.debug = debug
101
+ self.verbose = debug # Alias for compatibility
102
+
103
+ # Hot path tracking
104
+ self.hot_paths: Dict[str, HotPathInfo] = {}
105
+
106
+ # Compilation cache: bytecode_hash -> compiled_function
107
+ self.compilation_cache: Dict[str, Callable] = {}
108
+
109
+ # Statistics
110
+ self.stats = JITStats()
111
+
112
+ # Use advanced optimizer if available
113
+ if OPTIMIZER_AVAILABLE and optimization_level > 0:
114
+ self.optimizer = BytecodeOptimizer(level=optimization_level, max_passes=3, debug=False)
115
+ if self.debug:
116
+ print(f"🔧 JIT: Using BytecodeOptimizer (level {optimization_level})")
117
+ else:
118
+ self.optimizer = None
119
+ if self.debug and optimization_level > 0:
120
+ print("⚠️ JIT: BytecodeOptimizer not available, using basic optimization")
121
+
122
+ # Supported opcodes for JIT compilation
123
+ self.supported_opcodes = {
124
+ 'LOAD_CONST', 'LOAD_NAME', 'STORE_NAME', 'STORE_CONST',
125
+ 'ADD', 'SUB', 'MUL', 'DIV', 'MOD', 'POW',
126
+ 'EQ', 'NEQ', 'LT', 'GT', 'LTE', 'GTE',
127
+ 'AND', 'OR', 'NOT',
128
+ 'RETURN', 'JUMP', 'JUMP_IF_FALSE',
129
+ }
130
+
131
+ def should_compile(self, bytecode_hash: str) -> bool:
132
+ """
133
+ Determine if bytecode should be JIT compiled
134
+
135
+ Args:
136
+ bytecode_hash: Hash of the bytecode
137
+
138
+ Returns:
139
+ True if code is hot enough for JIT compilation
140
+ """
141
+ if bytecode_hash not in self.hot_paths:
142
+ return False
143
+
144
+ info = self.hot_paths[bytecode_hash]
145
+
146
+ # Check if already compiled
147
+ if info.tier == ExecutionTier.JIT_NATIVE:
148
+ return False
149
+
150
+ # Promote to JIT after threshold executions
151
+ if info.execution_count >= self.hot_threshold:
152
+ return True
153
+
154
+ return False
155
+
156
+ def track_execution(self, bytecode, execution_time: float = 0.0) -> HotPathInfo:
157
+ """
158
+ Track bytecode execution for hot path detection
159
+
160
+ Args:
161
+ bytecode: Bytecode object or instructions
162
+ execution_time: Time taken to execute
163
+
164
+ Returns:
165
+ HotPathInfo for the tracked bytecode
166
+ """
167
+ # Hash the bytecode for identification
168
+ bytecode_hash = self._hash_bytecode(bytecode)
169
+
170
+ if bytecode_hash not in self.hot_paths:
171
+ self.hot_paths[bytecode_hash] = HotPathInfo(
172
+ bytecode_hash=bytecode_hash,
173
+ tier=ExecutionTier.BYTECODE
174
+ )
175
+
176
+ info = self.hot_paths[bytecode_hash]
177
+ info.execution_count += 1
178
+ info.total_time += execution_time
179
+ info.average_time = info.total_time / info.execution_count
180
+ info.last_execution = time.time()
181
+
182
+ # Check for tier promotion
183
+ if info.execution_count == self.hot_threshold:
184
+ self.stats.hot_paths_detected += 1
185
+ if self.debug:
186
+ print(f"🔥 JIT: Hot path detected! Executed {info.execution_count} times "
187
+ f"(avg: {info.average_time*1000:.2f}ms)")
188
+
189
+ return info
190
+
191
+ def compile_hot_path(self, bytecode) -> Optional[Callable]:
192
+ """
193
+ Compile hot bytecode to optimized native code
194
+
195
+ Args:
196
+ bytecode: Bytecode object with instructions and constants
197
+
198
+ Returns:
199
+ Compiled function or None if compilation failed
200
+ """
201
+ # First check if bytecode is JIT-compatible
202
+ if not self._is_jit_compatible(bytecode):
203
+ if self.debug:
204
+ print(f"⚠️ JIT: Bytecode contains unsupported opcodes, skipping JIT")
205
+ return None
206
+
207
+ bytecode_hash = self._hash_bytecode(bytecode)
208
+
209
+ # Check cache first
210
+ if bytecode_hash in self.compilation_cache:
211
+ self.stats.cache_hits += 1
212
+ if self.debug:
213
+ print(f"✅ JIT: Cache hit for {bytecode_hash[:8]}")
214
+ return self.compilation_cache[bytecode_hash]
215
+
216
+ self.stats.cache_misses += 1
217
+
218
+ start_time = time.time()
219
+
220
+ try:
221
+ # Step 1: Analyze stack behavior
222
+ stack_frames = self._analyze_stack_behavior(bytecode)
223
+ if not stack_frames:
224
+ if self.debug:
225
+ print(f"❌ JIT: Failed to analyze stack behavior")
226
+ return None
227
+
228
+ # Step 2: Optimize bytecode
229
+ optimized_instructions, updated_constants = self._optimize_bytecode(bytecode)
230
+
231
+ # Step 3: Generate efficient Python source code
232
+ python_code = self._generate_efficient_python_code(
233
+ optimized_instructions,
234
+ updated_constants,
235
+ stack_frames
236
+ )
237
+
238
+ if self.debug and self.verbose:
239
+ print(f"📝 JIT Generated Python code:\n{python_code[:500]}...")
240
+
241
+ # Step 4: Compile to native Python bytecode
242
+ compiled = compile(python_code, f'<jit:{bytecode_hash[:8]}>', 'exec')
243
+
244
+ # Step 5: Create executable function
245
+ namespace = {'__builtins__': {}}
246
+ exec(compiled, namespace)
247
+ jit_function = namespace.get('jit_execute')
248
+
249
+ if jit_function:
250
+ # Verify the compiled function works
251
+ verification_result = self._verify_compilation(bytecode, jit_function)
252
+ if not verification_result:
253
+ if self.debug:
254
+ print(f"❌ JIT: Verification failed for {bytecode_hash[:8]}")
255
+ self.stats.compilation_failures += 1
256
+ return None
257
+
258
+ # Cache the compiled function
259
+ self.compilation_cache[bytecode_hash] = jit_function
260
+
261
+ # Update stats
262
+ compilation_time = time.time() - start_time
263
+ self.stats.compilations += 1
264
+ self.stats.compilation_time += compilation_time
265
+ self.stats.average_compilation_time = (
266
+ self.stats.compilation_time / self.stats.compilations
267
+ )
268
+ self.stats.tier_promotions += 1
269
+
270
+ # Update hot path info
271
+ if bytecode_hash in self.hot_paths:
272
+ info = self.hot_paths[bytecode_hash]
273
+ info.compiled_version = jit_function
274
+ info.compilation_time = compilation_time
275
+ info.tier = ExecutionTier.JIT_NATIVE
276
+
277
+ if self.debug:
278
+ print(f"✅ JIT: Compiled {bytecode_hash[:8]} in {compilation_time*1000:.2f}ms "
279
+ f"({len(optimized_instructions)} instructions)")
280
+
281
+ return jit_function
282
+
283
+ except Exception as e:
284
+ if self.debug:
285
+ print(f"❌ JIT: Compilation failed for {bytecode_hash[:8]}: {e}")
286
+ import traceback
287
+ traceback.print_exc()
288
+ self.stats.compilation_failures += 1
289
+ return None
290
+
291
+ return None
292
+
293
+ def get_stats(self) -> Dict[str, Any]:
294
+ """Get JIT compilation statistics"""
295
+ # Calculate speedup if we have enough data
296
+ speedup = 0.0
297
+ if (self.stats.total_jit_execution_time > 0 and
298
+ self.stats.total_bytecode_execution_time > 0 and
299
+ self.stats.jit_executions > 0):
300
+ avg_jit_time = self.stats.total_jit_execution_time / self.stats.jit_executions
301
+ avg_bytecode_time = self.stats.total_bytecode_execution_time / max(self.stats.jit_executions, 1)
302
+ speedup = avg_bytecode_time / avg_jit_time if avg_jit_time > 0 else 0
303
+
304
+ return {
305
+ 'hot_paths_detected': self.stats.hot_paths_detected,
306
+ 'compilations': self.stats.compilations,
307
+ 'compilation_time': round(self.stats.compilation_time, 4),
308
+ 'average_compilation_time': round(self.stats.average_compilation_time, 6),
309
+ 'jit_executions': self.stats.jit_executions,
310
+ 'total_jit_execution_time': round(self.stats.total_jit_execution_time, 4),
311
+ 'total_bytecode_execution_time': round(self.stats.total_bytecode_execution_time, 4),
312
+ 'speedup_factor': round(speedup, 2),
313
+ 'cache_hits': self.stats.cache_hits,
314
+ 'cache_misses': self.stats.cache_misses,
315
+ 'cache_size': len(self.compilation_cache),
316
+ 'tier_promotions': self.stats.tier_promotions,
317
+ 'compilation_failures': self.stats.compilation_failures,
318
+ 'cache_hit_rate': round(
319
+ self.stats.cache_hits / max(self.stats.cache_hits + self.stats.cache_misses, 1) * 100,
320
+ 1
321
+ ),
322
+ }
323
+
324
+ def clear_cache(self):
325
+ """Clear compilation cache"""
326
+ self.compilation_cache.clear()
327
+ self.hot_paths.clear()
328
+ self.stats = JITStats() # Reset stats
329
+ if self.debug:
330
+ print("🗑️ JIT: Cache cleared and stats reset")
331
+
332
+ def record_execution_time(self, bytecode_hash: str, execution_time: float, tier: ExecutionTier):
333
+ """
334
+ Record execution time for performance tracking
335
+
336
+ Args:
337
+ bytecode_hash: Hash of executed bytecode
338
+ execution_time: Time taken for execution
339
+ tier: Which tier was used for execution
340
+ """
341
+ if tier == ExecutionTier.JIT_NATIVE:
342
+ self.stats.jit_executions += 1
343
+ self.stats.total_jit_execution_time += execution_time
344
+
345
+ # Update speedup calculation in hot path info
346
+ if bytecode_hash in self.hot_paths:
347
+ info = self.hot_paths[bytecode_hash]
348
+ # Track for speedup calculation
349
+ if info.average_time > 0:
350
+ info.speedup_factor = info.average_time / execution_time
351
+ elif tier == ExecutionTier.BYTECODE:
352
+ # Track bytecode execution time for comparison
353
+ self.stats.total_bytecode_execution_time += execution_time
354
+
355
+ # ==================== Private Methods ====================
356
+
357
+ def _hash_bytecode(self, bytecode) -> str:
358
+ """Generate hash for bytecode identification"""
359
+ if hasattr(bytecode, 'instructions'):
360
+ # Bytecode object - include both instructions and constants
361
+ data = str(bytecode.instructions) + str(bytecode.constants)
362
+ elif hasattr(bytecode, '__iter__'):
363
+ # List of instructions
364
+ data = str(list(bytecode))
365
+ else:
366
+ data = str(bytecode)
367
+
368
+ return hashlib.sha256(data.encode()).hexdigest()[:16]
369
+
370
+ def _is_jit_compatible(self, bytecode) -> bool:
371
+ """Check if bytecode contains only JIT-supported opcodes"""
372
+ instructions = bytecode.instructions if hasattr(bytecode, 'instructions') else bytecode
373
+
374
+ for opcode, _ in instructions:
375
+ if opcode not in self.supported_opcodes:
376
+ if self.debug:
377
+ print(f"⚠️ JIT: Unsupported opcode: {opcode}")
378
+ return False
379
+ return True
380
+
381
+ def _analyze_stack_behavior(self, bytecode) -> List[StackFrame]:
382
+ """
383
+ Analyze stack behavior to generate efficient Python code
384
+
385
+ Returns:
386
+ List of StackFrame objects representing stack state at each instruction
387
+ """
388
+ instructions = bytecode.instructions if hasattr(bytecode, 'instructions') else bytecode
389
+ constants = bytecode.constants if hasattr(bytecode, 'constants') else []
390
+
391
+ frames = []
392
+ current_frame = StackFrame()
393
+
394
+ for i, (opcode, operand) in enumerate(instructions):
395
+ # Record current frame state
396
+ frames.append(StackFrame(
397
+ stack=list(current_frame.stack),
398
+ variables=dict(current_frame.variables),
399
+ constants=dict(current_frame.constants)
400
+ ))
401
+
402
+ # Update frame based on opcode
403
+ if opcode == 'LOAD_CONST':
404
+ # Create a unique variable name for this constant
405
+ var_name = f"const_{operand}_{i}"
406
+ current_frame.stack.append(var_name)
407
+ current_frame.constants[operand] = constants[operand] if operand < len(constants) else None
408
+ current_frame.variables[var_name] = repr(constants[operand]) if operand < len(constants) else 'None'
409
+
410
+ elif opcode == 'LOAD_NAME':
411
+ var_name = f"var_{operand}_{i}"
412
+ current_frame.stack.append(var_name)
413
+ # We don't know the value yet, will be looked up from env
414
+ current_frame.variables[var_name] = f"env.get({repr(constants[operand])}, None)" if operand < len(constants) else 'None'
415
+
416
+ elif opcode == 'STORE_NAME':
417
+ if current_frame.stack:
418
+ value_expr = current_frame.stack.pop()
419
+ name = constants[operand] if operand < len(constants) else f'unknown_{operand}'
420
+ current_frame.variables[name] = current_frame.variables.get(value_expr, value_expr)
421
+
422
+ elif opcode in ['ADD', 'SUB', 'MUL', 'DIV', 'MOD', 'POW']:
423
+ if len(current_frame.stack) >= 2:
424
+ b_expr = current_frame.stack.pop()
425
+ a_expr = current_frame.stack.pop()
426
+ result_expr = f"result_{i}"
427
+
428
+ a_val = current_frame.variables.get(a_expr, a_expr)
429
+ b_val = current_frame.variables.get(b_expr, b_expr)
430
+
431
+ # Try to evaluate if both are constants
432
+ try:
433
+ if (a_expr.startswith('const_') and b_expr.startswith('const_')):
434
+ # Both are constants, can pre-compute
435
+ a_const = eval(a_val) if isinstance(a_val, str) and a_val[0].isdigit() else a_val
436
+ b_const = eval(b_val) if isinstance(b_val, str) and b_val[0].isdigit() else b_val
437
+
438
+ if opcode == 'ADD':
439
+ result = a_const + b_const
440
+ elif opcode == 'SUB':
441
+ result = a_const - b_const
442
+ elif opcode == 'MUL':
443
+ result = a_const * b_const
444
+ elif opcode == 'DIV':
445
+ result = a_const / b_const if b_const != 0 else 0
446
+ elif opcode == 'MOD':
447
+ result = a_const % b_const if b_const != 0 else 0
448
+ elif opcode == 'POW':
449
+ result = a_const ** b_const
450
+
451
+ current_frame.variables[result_expr] = repr(result)
452
+ else:
453
+ # Runtime computation needed
454
+ current_frame.variables[result_expr] = f"({a_val} {self._opcode_to_operator(opcode)} {b_val})"
455
+ except (TypeError, ValueError, KeyError, NameError):
456
+ # Fallback to runtime computation
457
+ current_frame.variables[result_expr] = f"({a_val} {self._opcode_to_operator(opcode)} {b_val})"
458
+
459
+ current_frame.stack.append(result_expr)
460
+
461
+ elif opcode == 'RETURN':
462
+ if current_frame.stack:
463
+ return_expr = current_frame.stack[-1]
464
+ current_frame.variables['__return__'] = current_frame.variables.get(return_expr, return_expr)
465
+
466
+ return frames
467
+
468
+ def _opcode_to_operator(self, opcode: str) -> str:
469
+ """Convert opcode to Python operator"""
470
+ return {
471
+ 'ADD': '+',
472
+ 'SUB': '-',
473
+ 'MUL': '*',
474
+ 'DIV': '/',
475
+ 'MOD': '%',
476
+ 'POW': '**',
477
+ 'EQ': '==',
478
+ 'NEQ': '!=',
479
+ 'LT': '<',
480
+ 'GT': '>',
481
+ 'LTE': '<=',
482
+ 'GTE': '>=',
483
+ 'AND': 'and',
484
+ 'OR': 'or',
485
+ }.get(opcode, opcode)
486
+
487
+ def _optimize_bytecode(self, bytecode) -> Tuple[List, List]:
488
+ """
489
+ Apply optimization passes to bytecode
490
+
491
+ Returns: (optimized_instructions, updated_constants)
492
+ """
493
+ instructions = list(bytecode.instructions) if hasattr(bytecode, 'instructions') else list(bytecode)
494
+ constants = list(bytecode.constants) if hasattr(bytecode, 'constants') else []
495
+
496
+ if self.optimizer:
497
+ try:
498
+ optimized, updated_constants = self.optimizer.optimize(instructions, constants)
499
+ if self.debug:
500
+ stats = self.optimizer.get_stats()
501
+ if stats['total_optimizations'] > 0:
502
+ print(f"🔧 JIT Optimizer: {stats['original_size']} → {stats['optimized_size']} instructions "
503
+ f"({stats['size_reduction_pct']:.1f}% reduction)")
504
+ return optimized, updated_constants
505
+ except Exception as e:
506
+ if self.debug:
507
+ print(f"⚠️ JIT: Optimizer failed: {e}")
508
+ return instructions, constants
509
+
510
+ # Fallback: apply basic optimizations
511
+ optimized = self._apply_basic_optimizations(instructions, constants)
512
+ return optimized, constants
513
+
514
+ def _apply_basic_optimizations(self, instructions: List, constants: List) -> List:
515
+ """Apply basic peephole optimizations"""
516
+ optimized = []
517
+ i = 0
518
+
519
+ while i < len(instructions):
520
+ opcode, operand = instructions[i]
521
+
522
+ # Skip useless patterns
523
+ if i + 1 < len(instructions):
524
+ next_op, next_operand = instructions[i + 1]
525
+
526
+ # LOAD_CONST + POP -> skip both
527
+ if opcode == 'LOAD_CONST' and next_op == 'POP':
528
+ i += 2
529
+ continue
530
+
531
+ # LOAD_NAME + POP -> skip both
532
+ if opcode == 'LOAD_NAME' and next_op == 'POP':
533
+ i += 2
534
+ continue
535
+
536
+ optimized.append((opcode, operand))
537
+ i += 1
538
+
539
+ return optimized
540
+
541
+ def _generate_efficient_python_code(self, instructions: List, constants: List, stack_frames: List[StackFrame]) -> str:
542
+ """
543
+ Generate efficient Python source code from optimized bytecode
544
+ using stack analysis to minimize runtime checks
545
+ """
546
+ lines = [
547
+ "def jit_execute(vm, stack, env):",
548
+ " # JIT-compiled native code",
549
+ ]
550
+
551
+ # Track variable assignments for efficient code generation
552
+ local_vars = set()
553
+ stack_height = 0
554
+
555
+ for i, (opcode, operand) in enumerate(instructions):
556
+ if i >= len(stack_frames):
557
+ break
558
+
559
+ frame = stack_frames[i]
560
+
561
+ if opcode == 'LOAD_CONST':
562
+ if operand < len(constants):
563
+ const_val = constants[operand]
564
+ var_name = f"const_{operand}_{i}"
565
+ if var_name in frame.variables:
566
+ # Use pre-computed value if available
567
+ lines.append(f" {var_name} = {frame.variables[var_name]}")
568
+ local_vars.add(var_name)
569
+ lines.append(f" stack.append({var_name})")
570
+ else:
571
+ lines.append(f" stack.append({repr(const_val)})")
572
+ stack_height += 1
573
+
574
+ elif opcode == 'LOAD_NAME':
575
+ if operand < len(constants):
576
+ name = constants[operand]
577
+ var_name = f"var_{operand}_{i}"
578
+ if var_name in frame.variables:
579
+ # Use efficient lookup
580
+ lines.append(f" {var_name} = env.get({repr(name)}, None)")
581
+ local_vars.add(var_name)
582
+ lines.append(f" stack.append({var_name})")
583
+ else:
584
+ lines.append(f" stack.append(env.get({repr(name)}, None))")
585
+ stack_height += 1
586
+
587
+ elif opcode == 'STORE_NAME':
588
+ if operand < len(constants):
589
+ name = constants[operand]
590
+ if stack_height > 0:
591
+ lines.append(f" env[{repr(name)}] = stack.pop()")
592
+ stack_height -= 1
593
+
594
+ elif opcode == 'STORE_CONST':
595
+ if isinstance(operand, tuple) and len(operand) == 2:
596
+ name_idx, const_idx = operand
597
+ if name_idx < len(constants) and const_idx < len(constants):
598
+ name = constants[name_idx]
599
+ const_val = constants[const_idx]
600
+ lines.append(f" env[{repr(name)}] = {repr(const_val)}")
601
+
602
+ elif opcode in ['ADD', 'SUB', 'MUL', 'DIV', 'MOD', 'POW']:
603
+ if stack_height >= 2:
604
+ # Generate efficient arithmetic
605
+ operator = self._opcode_to_operator(opcode)
606
+ result_var = f"result_{i}"
607
+
608
+ # Try to use pre-computed values from stack analysis
609
+ if i > 0 and i-1 < len(stack_frames):
610
+ prev_frame = stack_frames[i-1]
611
+ if len(prev_frame.stack) >= 2:
612
+ a_expr = prev_frame.stack[-2]
613
+ b_expr = prev_frame.stack[-1]
614
+
615
+ if a_expr in frame.variables and b_expr in frame.variables:
616
+ # Both values are known, use pre-computation
617
+ a_val = frame.variables[a_expr]
618
+ b_val = frame.variables[b_expr]
619
+
620
+ # Check if we can compute at compile time
621
+ try:
622
+ if (a_expr.startswith('const_') and b_expr.startswith('const_')):
623
+ # Already computed by optimizer
624
+ computed = eval(f"{a_val} {operator} {b_val}")
625
+ lines.append(f" {result_var} = {repr(computed)}")
626
+ else:
627
+ lines.append(f" {result_var} = {a_val} {operator} {b_val}")
628
+ except (TypeError, ValueError, NameError, SyntaxError):
629
+ lines.append(f" {result_var} = {a_val} {operator} {b_val}")
630
+ else:
631
+ lines.append(f" b = stack.pop()")
632
+ lines.append(f" a = stack.pop()")
633
+ lines.append(f" {result_var} = a {operator} b")
634
+ else:
635
+ lines.append(f" b = stack.pop()")
636
+ lines.append(f" a = stack.pop()")
637
+ lines.append(f" {result_var} = a {operator} b")
638
+
639
+ local_vars.add(result_var)
640
+ lines.append(f" stack.append({result_var})")
641
+ stack_height -= 1 # 2 popped, 1 pushed = net -1
642
+
643
+ elif opcode == 'RETURN':
644
+ if stack_height > 0:
645
+ lines.append(" return stack[-1]")
646
+ else:
647
+ lines.append(" return None")
648
+ break
649
+
650
+ # Default return if no RETURN encountered
651
+ if not any(opcode == 'RETURN' for opcode, _ in instructions):
652
+ if stack_height > 0:
653
+ lines.append(" return stack[-1] if stack else None")
654
+ else:
655
+ lines.append(" return None")
656
+
657
+ return "\n".join(lines)
658
+
659
+ def _verify_compilation(self, original_bytecode, jit_function) -> bool:
660
+ """
661
+ Verify that JIT-compiled code produces same results as bytecode
662
+
663
+ Args:
664
+ original_bytecode: Original bytecode to verify against
665
+ jit_function: JIT-compiled function to verify
666
+
667
+ Returns:
668
+ True if verification passes
669
+ """
670
+ try:
671
+ # Create test environment
672
+ from .vm import VM
673
+
674
+ # Test with a few different inputs
675
+ test_cases = [
676
+ ({}, []), # Empty
677
+ ({'x': 5, 'y': 3}, []), # Some variables
678
+ ({'a': 10, 'b': 20, 'c': 30}, []), # More variables
679
+ ]
680
+
681
+ for env_dict, stack in test_cases:
682
+ # Run bytecode version
683
+ vm_bytecode = VM(use_jit=False)
684
+ vm_bytecode.env = env_dict.copy()
685
+ vm_bytecode.stack = stack.copy()
686
+ bytecode_result = vm_bytecode.execute(original_bytecode)
687
+
688
+ # Run JIT version
689
+ vm_jit = VM(use_jit=False)
690
+ vm_jit.env = env_dict.copy()
691
+ vm_jit.stack = stack.copy()
692
+ jit_result = jit_function(vm_jit, vm_jit.stack, vm_jit.env)
693
+
694
+ # Compare results
695
+ if bytecode_result != jit_result:
696
+ if self.debug:
697
+ print(f"❌ JIT Verification failed:")
698
+ print(f" Bytecode result: {bytecode_result}")
699
+ print(f" JIT result: {jit_result}")
700
+ print(f" Environment: {env_dict}")
701
+ return False
702
+
703
+ return True
704
+
705
+ except Exception as e:
706
+ if self.debug:
707
+ print(f"❌ JIT Verification error: {e}")
708
+ return False
709
+
710
+ def get_hot_path_info(self, bytecode_hash: str) -> Optional[HotPathInfo]:
711
+ """Get information about a hot path"""
712
+ return self.hot_paths.get(bytecode_hash)
713
+
714
+ def get_compilation_cache_info(self) -> Dict[str, Any]:
715
+ """Get information about compilation cache"""
716
+ return {
717
+ 'size': len(self.compilation_cache),
718
+ 'entries': list(self.compilation_cache.keys()),
719
+ 'hit_rate': self.stats.cache_hits / max(self.stats.cache_hits + self.stats.cache_misses, 1),
720
+ }