1313from .. import setproctitle
1414from ..cache import SharedCache
1515from ..clock import BeatCounter , system_clock
16- from ..language .vm import log_vm_stats
16+ from ..language .vm import log_vm_stats , ProgramInvalid
1717from ..model import Vector , StateDict , Context , null , numbers_cache_counts , empty_numbers_cache
1818from ..plugins import get_plugin
1919from ..render .window .models import Model
@@ -24,7 +24,7 @@ class EngineController:
2424 MINIMUM_GC_INTERVAL = 10
2525
2626 def __init__ (self , target_fps = 60 , screen = 0 , fullscreen = False , vsync = False , state_file = None ,
27- reset_on_switch = False , state_simplify_wait = 0 , realtime = True , defined_names = None , vm_stats = False ,
27+ reset_on_switch = False , realtime = True , defined_names = None , vm_stats = False ,
2828 run_time = None , offscreen = False , disable_simplifier = False , opengl_es = False , model_cache_time = 300 ):
2929 self .default_fps = target_fps
3030 self .target_fps = target_fps
@@ -37,7 +37,6 @@ def __init__(self, target_fps=60, screen=0, fullscreen=False, vsync=False, state
3737 self .model_cache_time = model_cache_time
3838 self .reset_on_switch = reset_on_switch
3939 self .disable_simplifier = disable_simplifier
40- self .state_simplify_wait = 0 if self .disable_simplifier else state_simplify_wait / 2
4140 if defined_names :
4241 self .defined_names = {key : Vector .coerce (value ) for key , value in defined_names .items ()}
4342 logger .trace ("Defined names: {!r}" , self .defined_names )
@@ -60,10 +59,6 @@ def __init__(self, target_fps=60, screen=0, fullscreen=False, vsync=False, state
6059 self .global_state = {}
6160 self .global_state_dirty = False
6261 self .state = None
63- self .state_timestamp = None
64- self .state_generation0 = None
65- self .state_generation1 = None
66- self .state_generation2 = None
6762 self .renderers = {}
6863 self .counter = BeatCounter ()
6964 self .pages = []
@@ -89,10 +84,6 @@ def switch_to_page(self, page_number):
8984 self .state .clear_changed ()
9085 path , state = self .pages [page_number ]
9186 self .state = state
92- self .state_timestamp = system_clock ()
93- self .state_generation0 = set ()
94- self .state_generation1 = set ()
95- self .state_generation2 = set ()
9687 self .current_path = path
9788 self .current_page = page_number
9889 SharedCache .set_root (self .current_path )
@@ -178,7 +169,8 @@ async def run(self):
178169 gc_pending = False
179170 last_gc = None
180171 run_program = current_program = errors = logs = None
181- simplify_state_time = frame_time + self .state_simplify_wait
172+ stables = set ()
173+ stable_cache = {}
182174 static = dict (self .defined_names )
183175 static .update ({'realtime' : self .realtime , 'screen' : self .screen , 'fullscreen' : self .fullscreen ,
184176 'vsync' : self .vsync , 'offscreen' : self .offscreen , 'opengl_es' : self .opengl_es , 'run_time' : self .run_time })
@@ -203,19 +195,20 @@ async def run(self):
203195 run_program = current_program = program
204196 self .handle_pragmas (program .pragmas , frame_time )
205197 errors = logs = None
206- self .state_generation0 ^= self .state_generation1
207- self .state_generation1 = self .state_generation2
208- self .state_generation2 = set ()
209- simplify_state_time = frame_time + self .state_simplify_wait
210198
211199 now = system_clock ()
212200 housekeeping += now
213201 execution -= now
214202
215203 if run_program is not None :
216204 context = Context (names = {key : Vector .coerce (value ) for key , value in dynamic .items ()},
217- state = self .state , references = self ._references )
218- run_program .run (context , record_stats = self .vm_stats )
205+ state = self .state , references = self ._references , stables = stables , stable_cache = stable_cache )
206+ try :
207+ run_program .run (context , record_stats = self .vm_stats )
208+ except ProgramInvalid :
209+ logger .debug ("Simplified program invalidated due to change of stable value" )
210+ run_program = current_program
211+ run_program .run (context , record_stats = self .vm_stats )
219212 else :
220213 context = Context ()
221214
@@ -240,50 +233,21 @@ async def run(self):
240233
241234 self .state ['_counter' ] = self .counter .tempo , self .counter .quantum , self .counter .start
242235
243- if self .state .changed :
244- if self .state_simplify_wait :
245- changed_keys = self .state .changed_keys - self .state_generation0
246- self .state_generation0 ^= changed_keys
247- self .state_generation0 &= self .state .keys ()
248- if changed_keys :
249- generation1to0 = self .state_generation1 & changed_keys
250- changed_keys -= generation1to0
251- self .state_generation1 -= generation1to0
252- generation2to0 = self .state_generation2 & changed_keys
253- if generation2to0 :
254- if run_program is not current_program :
255- run_program = current_program
256- logger .debug ("Undo simplification on state; original program with {} instructions" , len (run_program ))
257- self .state_generation1 ^= self .state_generation2 - generation2to0
258- self .state_generation2 = set ()
259- simplify_state_time = frame_time + self .state_simplify_wait
260- self .global_state_dirty = True
261- self .state_timestamp = frame_time
262- self .state .clear_changed ()
263-
264- if self .state_simplify_wait and frame_time > simplify_state_time :
265- if current_program is not None and self .state_generation1 :
266- if self .state_generation1 :
267- self .state_generation2 ^= self .state_generation1
268- simplify_state = self .state .with_keys (self .state_generation2 )
269- simplify_time = - system_clock ()
270- top = current_program .top .simplify (state = simplify_state , dynamic = dynamic , path = current_program .path )
271- now = system_clock ()
272- simplify_time += now
273- if top is current_program .top :
274- logger .trace ("Program unchanged after simplification on {} static state keys in {:.1f}ms" ,
275- len (self .state_generation2 ), simplify_time * 1000 )
276- else :
277- compile_time = - now
278- run_program = top .compile (initial_lnames = tuple (dynamic ))
279- run_program .set_path (current_program .path )
280- run_program .set_top (top )
281- compile_time += system_clock ()
282- logger .debug ("Simplified on {} static state keys to {} instructions in {:.1f}/{:.1f}ms" ,
283- len (self .state_generation2 ), len (run_program ), simplify_time * 1000 , compile_time * 1000 )
284- self .state_generation1 = self .state_generation0
285- self .state_generation0 = set ()
286- simplify_state_time = frame_time + self .state_simplify_wait
236+ if not self .disable_simplifier and context .stables_changed and current_program is not None :
237+ simplify_time = - system_clock ()
238+ top = current_program .top .simplify (dynamic = dynamic , path = current_program .path , stables = stables , stable_cache = stable_cache )
239+ now = system_clock ()
240+ simplify_time += now
241+ if top is current_program .top :
242+ logger .trace ("Program unchanged after simplification on stable values in {:.1f}ms" , simplify_time * 1000 )
243+ else :
244+ compile_time = - now
245+ run_program = top .compile (initial_lnames = tuple (dynamic ), stables = stables )
246+ run_program .set_path (current_program .path )
247+ run_program .set_top (top )
248+ compile_time += system_clock ()
249+ logger .debug ("Resimplified on stable values to {} instructions in {:.1f}/{:.1f}ms" ,
250+ len (run_program ), simplify_time * 1000 , compile_time * 1000 )
287251
288252 if self .global_state_dirty and self .state_file is not None and frame_time > save_state_time :
289253 logger .trace ("Saving state" )
0 commit comments