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,452 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Bytecode Peephole Optimizer for Zexus VM
|
|
3
|
+
|
|
4
|
+
Implements peephole optimization patterns including:
|
|
5
|
+
- Constant folding
|
|
6
|
+
- Dead code elimination
|
|
7
|
+
- Strength reduction
|
|
8
|
+
- Instruction fusion
|
|
9
|
+
- Jump threading
|
|
10
|
+
|
|
11
|
+
Phase 8.3 of VM Optimization Project
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from dataclasses import dataclass, field
|
|
15
|
+
from typing import List, Dict, Optional, Tuple, Any
|
|
16
|
+
from enum import Enum
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class OptimizationLevel(Enum):
|
|
20
|
+
"""Optimization levels"""
|
|
21
|
+
NONE = 0 # No optimization
|
|
22
|
+
BASIC = 1 # Safe, basic optimizations
|
|
23
|
+
MODERATE = 2 # More aggressive optimizations
|
|
24
|
+
AGGRESSIVE = 3 # Maximum optimization
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class Instruction:
|
|
29
|
+
"""Bytecode instruction representation"""
|
|
30
|
+
opcode: str
|
|
31
|
+
arg: Optional[Any] = None
|
|
32
|
+
lineno: int = 0
|
|
33
|
+
|
|
34
|
+
def __repr__(self):
|
|
35
|
+
if self.arg is not None:
|
|
36
|
+
return f"{self.opcode}({self.arg})"
|
|
37
|
+
return self.opcode
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass
|
|
41
|
+
class OptimizationStats:
|
|
42
|
+
"""Statistics for optimizations performed"""
|
|
43
|
+
constant_folds: int = 0
|
|
44
|
+
dead_code_eliminated: int = 0
|
|
45
|
+
strength_reductions: int = 0
|
|
46
|
+
instruction_fusions: int = 0
|
|
47
|
+
jump_threads: int = 0
|
|
48
|
+
total_instructions_removed: int = 0
|
|
49
|
+
original_size: int = 0
|
|
50
|
+
optimized_size: int = 0
|
|
51
|
+
|
|
52
|
+
def to_dict(self) -> dict:
|
|
53
|
+
"""Convert stats to dictionary"""
|
|
54
|
+
return {
|
|
55
|
+
'constant_folds': self.constant_folds,
|
|
56
|
+
'dead_code_eliminated': self.dead_code_eliminated,
|
|
57
|
+
'strength_reductions': self.strength_reductions,
|
|
58
|
+
'instruction_fusions': self.instruction_fusions,
|
|
59
|
+
'jump_threads': self.jump_threads,
|
|
60
|
+
'total_instructions_removed': self.total_instructions_removed,
|
|
61
|
+
'original_size': self.original_size,
|
|
62
|
+
'optimized_size': self.optimized_size,
|
|
63
|
+
'reduction_percent': self._reduction_percent(),
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
def _reduction_percent(self) -> float:
|
|
67
|
+
"""Calculate reduction percentage"""
|
|
68
|
+
if self.original_size == 0:
|
|
69
|
+
return 0.0
|
|
70
|
+
removed = self.original_size - self.optimized_size
|
|
71
|
+
return (removed / self.original_size) * 100.0
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class PeepholeOptimizer:
|
|
75
|
+
"""
|
|
76
|
+
Peephole optimizer for Zexus bytecode
|
|
77
|
+
|
|
78
|
+
Analyzes small windows of instructions (typically 2-4) and applies
|
|
79
|
+
local optimizations.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
def __init__(self, level: OptimizationLevel = OptimizationLevel.BASIC):
|
|
83
|
+
self.level = level
|
|
84
|
+
self.stats = OptimizationStats()
|
|
85
|
+
|
|
86
|
+
# Optimization pattern matchers
|
|
87
|
+
self.patterns = {
|
|
88
|
+
OptimizationLevel.BASIC: [
|
|
89
|
+
self._fold_constants,
|
|
90
|
+
self._eliminate_nops,
|
|
91
|
+
],
|
|
92
|
+
OptimizationLevel.MODERATE: [
|
|
93
|
+
self._fold_constants,
|
|
94
|
+
self._eliminate_nops,
|
|
95
|
+
self._eliminate_dead_stores,
|
|
96
|
+
self._fuse_load_store,
|
|
97
|
+
],
|
|
98
|
+
OptimizationLevel.AGGRESSIVE: [
|
|
99
|
+
self._fold_constants,
|
|
100
|
+
self._eliminate_nops,
|
|
101
|
+
self._eliminate_dead_stores,
|
|
102
|
+
self._fuse_load_store,
|
|
103
|
+
self._strength_reduce,
|
|
104
|
+
self._thread_jumps,
|
|
105
|
+
],
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
def optimize(self, instructions: List[Instruction]) -> List[Instruction]:
|
|
109
|
+
"""
|
|
110
|
+
Optimize a list of instructions
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
instructions: List of bytecode instructions
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Optimized instruction list
|
|
117
|
+
"""
|
|
118
|
+
if self.level == OptimizationLevel.NONE:
|
|
119
|
+
return instructions
|
|
120
|
+
|
|
121
|
+
# Reset stats
|
|
122
|
+
self.stats = OptimizationStats()
|
|
123
|
+
self.stats.original_size = len(instructions)
|
|
124
|
+
|
|
125
|
+
# Apply optimization passes
|
|
126
|
+
optimized = instructions[:]
|
|
127
|
+
|
|
128
|
+
# Multiple passes until no more changes
|
|
129
|
+
max_passes = 5
|
|
130
|
+
for pass_num in range(max_passes):
|
|
131
|
+
old_len = len(optimized)
|
|
132
|
+
|
|
133
|
+
# Apply all patterns for this optimization level
|
|
134
|
+
for pattern in self.patterns[self.level]:
|
|
135
|
+
optimized = self._apply_pattern(optimized, pattern)
|
|
136
|
+
|
|
137
|
+
# Stop if no changes
|
|
138
|
+
if len(optimized) == old_len:
|
|
139
|
+
break
|
|
140
|
+
|
|
141
|
+
self.stats.optimized_size = len(optimized)
|
|
142
|
+
self.stats.total_instructions_removed = (
|
|
143
|
+
self.stats.original_size - self.stats.optimized_size
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
return optimized
|
|
147
|
+
|
|
148
|
+
def _apply_pattern(
|
|
149
|
+
self,
|
|
150
|
+
instructions: List[Instruction],
|
|
151
|
+
pattern_func
|
|
152
|
+
) -> List[Instruction]:
|
|
153
|
+
"""Apply a pattern to all instruction windows"""
|
|
154
|
+
result = []
|
|
155
|
+
i = 0
|
|
156
|
+
|
|
157
|
+
while i < len(instructions):
|
|
158
|
+
# Try to match pattern at current position
|
|
159
|
+
matched, replacement, consumed = pattern_func(instructions, i)
|
|
160
|
+
|
|
161
|
+
if matched:
|
|
162
|
+
# Pattern matched - add replacement
|
|
163
|
+
result.extend(replacement)
|
|
164
|
+
i += consumed
|
|
165
|
+
else:
|
|
166
|
+
# No match - keep original
|
|
167
|
+
result.append(instructions[i])
|
|
168
|
+
i += 1
|
|
169
|
+
|
|
170
|
+
return result
|
|
171
|
+
|
|
172
|
+
# ========== Constant Folding ==========
|
|
173
|
+
|
|
174
|
+
def _fold_constants(
|
|
175
|
+
self,
|
|
176
|
+
instructions: List[Instruction],
|
|
177
|
+
pos: int
|
|
178
|
+
) -> Tuple[bool, List[Instruction], int]:
|
|
179
|
+
"""
|
|
180
|
+
Fold constant arithmetic operations
|
|
181
|
+
|
|
182
|
+
Patterns:
|
|
183
|
+
- LOAD_CONST a, LOAD_CONST b, ADD -> LOAD_CONST (a+b)
|
|
184
|
+
- LOAD_CONST a, LOAD_CONST b, SUB -> LOAD_CONST (a-b)
|
|
185
|
+
- LOAD_CONST a, LOAD_CONST b, MUL -> LOAD_CONST (a*b)
|
|
186
|
+
- LOAD_CONST a, LOAD_CONST b, DIV -> LOAD_CONST (a/b)
|
|
187
|
+
"""
|
|
188
|
+
if pos + 2 >= len(instructions):
|
|
189
|
+
return False, [], 0
|
|
190
|
+
|
|
191
|
+
inst1 = instructions[pos]
|
|
192
|
+
inst2 = instructions[pos + 1]
|
|
193
|
+
inst3 = instructions[pos + 2]
|
|
194
|
+
|
|
195
|
+
# Check for LOAD_CONST, LOAD_CONST, BINARY_OP pattern
|
|
196
|
+
if (inst1.opcode == 'LOAD_CONST' and
|
|
197
|
+
inst2.opcode == 'LOAD_CONST' and
|
|
198
|
+
inst3.opcode in ('ADD', 'SUB', 'MUL', 'DIV', 'MOD',
|
|
199
|
+
'BINARY_ADD', 'BINARY_SUB', 'BINARY_MUL',
|
|
200
|
+
'BINARY_DIV', 'BINARY_MOD')):
|
|
201
|
+
|
|
202
|
+
# Both operands must be constants
|
|
203
|
+
a = inst1.arg
|
|
204
|
+
b = inst2.arg
|
|
205
|
+
|
|
206
|
+
# Only fold numeric constants
|
|
207
|
+
if not (isinstance(a, (int, float)) and isinstance(b, (int, float))):
|
|
208
|
+
return False, [], 0
|
|
209
|
+
|
|
210
|
+
try:
|
|
211
|
+
# Compute result
|
|
212
|
+
op = inst3.opcode
|
|
213
|
+
if op in ('ADD', 'BINARY_ADD'):
|
|
214
|
+
result = a + b
|
|
215
|
+
elif op in ('SUB', 'BINARY_SUB'):
|
|
216
|
+
result = a - b
|
|
217
|
+
elif op in ('MUL', 'BINARY_MUL'):
|
|
218
|
+
result = a * b
|
|
219
|
+
elif op in ('DIV', 'BINARY_DIV'):
|
|
220
|
+
if b == 0:
|
|
221
|
+
return False, [], 0
|
|
222
|
+
result = a / b
|
|
223
|
+
elif op in ('MOD', 'BINARY_MOD'):
|
|
224
|
+
if b == 0:
|
|
225
|
+
return False, [], 0
|
|
226
|
+
result = a % b
|
|
227
|
+
else:
|
|
228
|
+
return False, [], 0
|
|
229
|
+
|
|
230
|
+
# Replace with single LOAD_CONST
|
|
231
|
+
replacement = [Instruction('LOAD_CONST', result, inst1.lineno)]
|
|
232
|
+
self.stats.constant_folds += 1
|
|
233
|
+
return True, replacement, 3
|
|
234
|
+
|
|
235
|
+
except (ZeroDivisionError, OverflowError, ValueError):
|
|
236
|
+
# Can't fold if operation would fail
|
|
237
|
+
return False, [], 0
|
|
238
|
+
|
|
239
|
+
return False, [], 0
|
|
240
|
+
|
|
241
|
+
# ========== Dead Code Elimination ==========
|
|
242
|
+
|
|
243
|
+
def _eliminate_nops(
|
|
244
|
+
self,
|
|
245
|
+
instructions: List[Instruction],
|
|
246
|
+
pos: int
|
|
247
|
+
) -> Tuple[bool, List[Instruction], int]:
|
|
248
|
+
"""
|
|
249
|
+
Eliminate NOP instructions and useless operations
|
|
250
|
+
|
|
251
|
+
Patterns:
|
|
252
|
+
- NOP -> (removed)
|
|
253
|
+
- LOAD_CONST x, POP_TOP -> (removed)
|
|
254
|
+
- DUP_TOP, POP_TOP -> (removed)
|
|
255
|
+
"""
|
|
256
|
+
inst = instructions[pos]
|
|
257
|
+
|
|
258
|
+
# Remove NOPs
|
|
259
|
+
if inst.opcode == 'NOP':
|
|
260
|
+
self.stats.dead_code_eliminated += 1
|
|
261
|
+
return True, [], 1
|
|
262
|
+
|
|
263
|
+
# LOAD_CONST followed by POP_TOP
|
|
264
|
+
if pos + 1 < len(instructions):
|
|
265
|
+
next_inst = instructions[pos + 1]
|
|
266
|
+
|
|
267
|
+
if inst.opcode == 'LOAD_CONST' and next_inst.opcode == 'POP_TOP':
|
|
268
|
+
self.stats.dead_code_eliminated += 1
|
|
269
|
+
return True, [], 2
|
|
270
|
+
|
|
271
|
+
# DUP_TOP followed by POP_TOP
|
|
272
|
+
if inst.opcode == 'DUP_TOP' and next_inst.opcode == 'POP_TOP':
|
|
273
|
+
self.stats.dead_code_eliminated += 1
|
|
274
|
+
return True, [], 2
|
|
275
|
+
|
|
276
|
+
return False, [], 0
|
|
277
|
+
|
|
278
|
+
def _eliminate_dead_stores(
|
|
279
|
+
self,
|
|
280
|
+
instructions: List[Instruction],
|
|
281
|
+
pos: int
|
|
282
|
+
) -> Tuple[bool, List[Instruction], int]:
|
|
283
|
+
"""
|
|
284
|
+
Eliminate stores to variables that are never read
|
|
285
|
+
|
|
286
|
+
Patterns:
|
|
287
|
+
- STORE_FAST x, LOAD_FAST y (x != y) -> STORE_FAST x (if x not used)
|
|
288
|
+
- STORE_FAST x, STORE_FAST x -> STORE_FAST x
|
|
289
|
+
"""
|
|
290
|
+
if pos + 1 >= len(instructions):
|
|
291
|
+
return False, [], 0
|
|
292
|
+
|
|
293
|
+
inst1 = instructions[pos]
|
|
294
|
+
inst2 = instructions[pos + 1]
|
|
295
|
+
|
|
296
|
+
# Double store to same variable
|
|
297
|
+
if (inst1.opcode == 'STORE_FAST' and
|
|
298
|
+
inst2.opcode == 'STORE_FAST' and
|
|
299
|
+
inst1.arg == inst2.arg):
|
|
300
|
+
# First store is overwritten - remove it
|
|
301
|
+
# Keep second store but need the value for it
|
|
302
|
+
self.stats.dead_code_eliminated += 1
|
|
303
|
+
return True, [inst2], 2
|
|
304
|
+
|
|
305
|
+
return False, [], 0
|
|
306
|
+
|
|
307
|
+
# ========== Strength Reduction ==========
|
|
308
|
+
|
|
309
|
+
def _strength_reduce(
|
|
310
|
+
self,
|
|
311
|
+
instructions: List[Instruction],
|
|
312
|
+
pos: int
|
|
313
|
+
) -> Tuple[bool, List[Instruction], int]:
|
|
314
|
+
"""
|
|
315
|
+
Replace expensive operations with cheaper equivalents
|
|
316
|
+
|
|
317
|
+
Patterns:
|
|
318
|
+
- x * 2 -> x << 1 (x + x)
|
|
319
|
+
- x / 2 -> x >> 1
|
|
320
|
+
- x * 1 -> x
|
|
321
|
+
- x * 0 -> 0
|
|
322
|
+
"""
|
|
323
|
+
if pos + 2 >= len(instructions):
|
|
324
|
+
return False, [], 0
|
|
325
|
+
|
|
326
|
+
inst1 = instructions[pos]
|
|
327
|
+
inst2 = instructions[pos + 1]
|
|
328
|
+
inst3 = instructions[pos + 2]
|
|
329
|
+
|
|
330
|
+
# Check for LOAD_VAR, LOAD_CONST, MUL pattern
|
|
331
|
+
if (inst1.opcode in ('LOAD_FAST', 'LOAD_NAME', 'LOAD_GLOBAL') and
|
|
332
|
+
inst2.opcode == 'LOAD_CONST' and
|
|
333
|
+
inst3.opcode in ('MUL', 'BINARY_MUL')):
|
|
334
|
+
|
|
335
|
+
const = inst2.arg
|
|
336
|
+
|
|
337
|
+
# x * 0 = 0
|
|
338
|
+
if const == 0:
|
|
339
|
+
replacement = [Instruction('LOAD_CONST', 0, inst1.lineno)]
|
|
340
|
+
self.stats.strength_reductions += 1
|
|
341
|
+
return True, replacement, 3
|
|
342
|
+
|
|
343
|
+
# x * 1 = x
|
|
344
|
+
if const == 1:
|
|
345
|
+
replacement = [inst1]
|
|
346
|
+
self.stats.strength_reductions += 1
|
|
347
|
+
return True, replacement, 3
|
|
348
|
+
|
|
349
|
+
# x * 2 = x + x
|
|
350
|
+
if const == 2:
|
|
351
|
+
replacement = [
|
|
352
|
+
inst1,
|
|
353
|
+
Instruction('DUP_TOP', None, inst1.lineno),
|
|
354
|
+
Instruction('ADD', None, inst1.lineno),
|
|
355
|
+
]
|
|
356
|
+
self.stats.strength_reductions += 1
|
|
357
|
+
return True, replacement, 3
|
|
358
|
+
|
|
359
|
+
# x * power of 2 = x << n
|
|
360
|
+
if isinstance(const, int) and const > 0 and (const & (const - 1)) == 0:
|
|
361
|
+
shift = (const - 1).bit_length()
|
|
362
|
+
replacement = [
|
|
363
|
+
inst1,
|
|
364
|
+
Instruction('LOAD_CONST', shift, inst1.lineno),
|
|
365
|
+
Instruction('LSHIFT', None, inst1.lineno),
|
|
366
|
+
]
|
|
367
|
+
self.stats.strength_reductions += 1
|
|
368
|
+
return True, replacement, 3
|
|
369
|
+
|
|
370
|
+
return False, [], 0
|
|
371
|
+
|
|
372
|
+
# ========== Instruction Fusion ==========
|
|
373
|
+
|
|
374
|
+
def _fuse_load_store(
|
|
375
|
+
self,
|
|
376
|
+
instructions: List[Instruction],
|
|
377
|
+
pos: int
|
|
378
|
+
) -> Tuple[bool, List[Instruction], int]:
|
|
379
|
+
"""
|
|
380
|
+
Fuse common load/store patterns
|
|
381
|
+
|
|
382
|
+
Patterns:
|
|
383
|
+
- LOAD_FAST x, STORE_FAST y -> COPY_FAST x, y (if available)
|
|
384
|
+
- LOAD_CONST x, STORE_FAST y -> (keep as is, already minimal)
|
|
385
|
+
"""
|
|
386
|
+
if pos + 1 >= len(instructions):
|
|
387
|
+
return False, [], 0
|
|
388
|
+
|
|
389
|
+
inst1 = instructions[pos]
|
|
390
|
+
inst2 = instructions[pos + 1]
|
|
391
|
+
|
|
392
|
+
# LOAD_FAST x, STORE_FAST x (reload same variable)
|
|
393
|
+
if (inst1.opcode == 'LOAD_FAST' and
|
|
394
|
+
inst2.opcode == 'STORE_FAST' and
|
|
395
|
+
inst1.arg == inst2.arg):
|
|
396
|
+
# This is a no-op if nothing else happens
|
|
397
|
+
# But we need to be careful - stack effect matters
|
|
398
|
+
# Keep the LOAD_FAST, remove STORE_FAST
|
|
399
|
+
# Actually, this is LOAD then immediately STORE to same var
|
|
400
|
+
# which means we pop and push same value - effectively DUP_TOP, POP_TOP
|
|
401
|
+
# Can be eliminated if next instruction doesn't need the value
|
|
402
|
+
return False, [], 0
|
|
403
|
+
|
|
404
|
+
return False, [], 0
|
|
405
|
+
|
|
406
|
+
# ========== Jump Threading ==========
|
|
407
|
+
|
|
408
|
+
def _thread_jumps(
|
|
409
|
+
self,
|
|
410
|
+
instructions: List[Instruction],
|
|
411
|
+
pos: int
|
|
412
|
+
) -> Tuple[bool, List[Instruction], int]:
|
|
413
|
+
"""
|
|
414
|
+
Thread jumps through other jumps
|
|
415
|
+
|
|
416
|
+
Patterns:
|
|
417
|
+
- JUMP_IF_TRUE L1, L1: JUMP_IF_TRUE L2 -> JUMP_IF_TRUE L2
|
|
418
|
+
- JUMP L1, L1: JUMP L2 -> JUMP L2
|
|
419
|
+
"""
|
|
420
|
+
inst = instructions[pos]
|
|
421
|
+
|
|
422
|
+
# For now, skip jump threading as it requires label resolution
|
|
423
|
+
# Would need full control flow analysis
|
|
424
|
+
return False, [], 0
|
|
425
|
+
|
|
426
|
+
def get_stats(self) -> Dict[str, Any]:
|
|
427
|
+
"""Get optimization statistics"""
|
|
428
|
+
return self.stats.to_dict()
|
|
429
|
+
|
|
430
|
+
def reset_stats(self):
|
|
431
|
+
"""Reset statistics"""
|
|
432
|
+
self.stats = OptimizationStats()
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
def optimize_bytecode(
|
|
436
|
+
instructions: List[Instruction],
|
|
437
|
+
level: OptimizationLevel = OptimizationLevel.BASIC
|
|
438
|
+
) -> Tuple[List[Instruction], Dict[str, Any]]:
|
|
439
|
+
"""
|
|
440
|
+
Convenience function to optimize bytecode
|
|
441
|
+
|
|
442
|
+
Args:
|
|
443
|
+
instructions: List of bytecode instructions
|
|
444
|
+
level: Optimization level
|
|
445
|
+
|
|
446
|
+
Returns:
|
|
447
|
+
Tuple of (optimized instructions, statistics)
|
|
448
|
+
"""
|
|
449
|
+
optimizer = PeepholeOptimizer(level)
|
|
450
|
+
optimized = optimizer.optimize(instructions)
|
|
451
|
+
stats = optimizer.get_stats()
|
|
452
|
+
return optimized, stats
|