@@ -57,10 +57,12 @@ pub struct VM {
5757 compiled_fn_cache : HashMap < SymbolKey , Rc < Chunk > > ,
5858 // For native functions, we only need the function pointer
5959 native_fn_cache : HashMap < SymbolKey , fn ( & [ Value ] ) -> Result < Value , String > > ,
60- // JIT compiler (lazily initialized)
60+ // JIT compiler (lazily initialized when jit_enabled is true )
6161 jit : Option < JitCompiler > ,
6262 // Call counts for JIT compilation triggering (chunk pointer -> count)
6363 call_counts : HashMap < usize , u32 > ,
64+ // JIT enabled flag (opt-in via --jit flag)
65+ jit_enabled : bool ,
6466}
6567
6668impl VM {
@@ -74,6 +76,7 @@ impl VM {
7476 native_fn_cache : HashMap :: new ( ) ,
7577 jit : None ,
7678 call_counts : HashMap :: new ( ) ,
79+ jit_enabled : false ,
7780 }
7881 }
7982
@@ -87,9 +90,15 @@ impl VM {
8790 native_fn_cache : HashMap :: new ( ) ,
8891 jit : None ,
8992 call_counts : HashMap :: new ( ) ,
93+ jit_enabled : false ,
9094 }
9195 }
9296
97+ /// Enable JIT compilation (opt-in via --jit flag)
98+ pub fn enable_jit ( & mut self ) {
99+ self . jit_enabled = true ;
100+ }
101+
93102 pub fn define_global ( & mut self , name : & str , value : Value ) {
94103 // Avoid String allocation if key already exists
95104 {
@@ -431,33 +440,35 @@ impl VM {
431440 }
432441 }
433442
434- // Try JIT execution first (fast path)
435- if let Some ( jit) = & self . jit {
436- if let Some ( jit_code) = jit. get_compiled ( chunk_ptr) {
437- let result = unsafe {
438- jit_code. execute ( & mut self . registers [ new_base..new_base + cf_num_registers] )
439- } ;
440- if let Ok ( value) = result {
441- // JIT succeeded - store result and continue
442- unsafe { * self . registers . get_unchecked_mut ( base + dest as usize ) = value } ;
443- continue ;
443+ // Try JIT execution first (fast path) - only if JIT is enabled
444+ if self . jit_enabled {
445+ if let Some ( jit) = & self . jit {
446+ if let Some ( jit_code) = jit. get_compiled ( chunk_ptr) {
447+ let result = unsafe {
448+ jit_code. execute ( & mut self . registers [ new_base..new_base + cf_num_registers] )
449+ } ;
450+ if let Ok ( value) = result {
451+ // JIT succeeded - store result and continue
452+ unsafe { * self . registers . get_unchecked_mut ( base + dest as usize ) = value } ;
453+ continue ;
454+ }
444455 }
445456 }
446- }
447457
448- // JIT not available or failed - fall back to interpreter
449- // Update call count for potential future JIT compilation
450- {
451- let count = self . call_counts . entry ( chunk_ptr) . or_insert ( 0 ) ;
452- * count += 1 ;
453- if * count == JIT_THRESHOLD && is_jit_compatible ( & cf_chunk) {
454- // Trigger JIT compilation (lazily, will be used on next call)
455- if self . jit . is_none ( ) {
456- self . jit = JitCompiler :: new ( ) . ok ( ) ;
457- }
458- if let Some ( jit) = & mut self . jit {
459- let name = format ! ( "jit_func_{:x}" , chunk_ptr) ;
460- let _ = jit. compile_function ( & cf_chunk, & name) ;
458+ // JIT not available or failed - fall back to interpreter
459+ // Update call count for potential future JIT compilation
460+ {
461+ let count = self . call_counts . entry ( chunk_ptr) . or_insert ( 0 ) ;
462+ * count += 1 ;
463+ if * count == JIT_THRESHOLD && is_jit_compatible ( & cf_chunk) {
464+ // Trigger JIT compilation (lazily, will be used on next call)
465+ if self . jit . is_none ( ) {
466+ self . jit = JitCompiler :: new ( ) . ok ( ) ;
467+ }
468+ if let Some ( jit) = & mut self . jit {
469+ let name = format ! ( "jit_func_{:x}" , chunk_ptr) ;
470+ let _ = jit. compile_function ( & cf_chunk, & name) ;
471+ }
461472 }
462473 }
463474 }
0 commit comments