MCPcopy Create free account
hub / github.com/dylan-sutton-chavez/edge-python / exec

Method exec

compiler/src/modules/vm/dispatch.rs:145–257  ·  view source on GitHub ↗

Main dispatch loop. Walks the fused instruction stream (LoadAttr+Call already collapsed to CallMethod+CallMethodArgs); checks the IC inline for hot arith/compare opcodes. */

(&mut self, chunk: &SSAChunk, slots: &mut [Val])

Source from the content-addressed store, hash-verified

143
144 /* Main dispatch loop. Walks the fused instruction stream (LoadAttr+Call already collapsed to CallMethod+CallMethodArgs); checks the IC inline for hot arith/compare opcodes. */
145 pub(crate) fn exec(&mut self, chunk: &SSAChunk, slots: &mut [Val]) -> Result<Val, VmErr> {
146
147 let slots_base = self.live_slots.len();
148 // `resume_coroutine` pre-pushes restored exception frames before calling us; honor its override so dispatch's handler search includes them.
149 let exc_base = self.pending_exec_exc_base.take().unwrap_or(self.exception_stack.len());
150 // Cleanup reasons belong to this frame's finally bodies; drop leftovers when it returns.
151 let unwind_base = self.unwind_stack.len();
152 let key = chunk as *const _;
153
154 let mut cache = self.opcode_caches.remove(&key).unwrap_or_else(|| OpcodeCache::new(chunk));
155 cache.ensure_fused(chunk);
156 // Pre-materialise the constant pool here (not in OpcodeCache::new) because Str allocates into the live HeapPool.
157 if let Err(e) = cache.ensure_const_vals(chunk, &mut self.heap) {
158 self.opcode_caches.insert(key, cache);
159 return Err(e);
160 }
161
162 // Hoist slices out of the loop; cache outlives exec() and isn't mutated meanwhile.
163 let insns_ptr: *const [Instruction] = cache.fused_ref();
164 let consts_ptr: *const [Val] = cache.const_vals_ref();
165 self.active_const_pools.push(consts_ptr);
166 let result: Result<Val, VmErr> = (|| {
167 // SAFETY: see comment above.
168 let insns: &[Instruction] = unsafe { &*insns_ptr };
169 let consts: &[Val] = unsafe { &*consts_ptr };
170 let n = insns.len();
171 let mut ip = self.resume_ip;
172 self.resume_ip = 0;
173
174 loop {
175 if ip >= n {
176 self.exception_stack.truncate(exc_base);
177 self.unwind_stack.truncate(unwind_base);
178 return Ok(Val::none());
179 }
180
181 let rip = ip;
182 match self.dispatch(chunk, slots, &mut cache, insns, consts, &mut ip, exc_base) {
183 Ok(None) => {
184 if self.yielded {
185 // Event yields keep the None placeholder (overwritten by `run_push_event` before resume). Sync sub-call yields pushed nothing, the helper's return lands on the stack when its frame completes, so don't pop and don't skip the next PopTop. Child-wait yields keep the placeholder (wake-loop overwrites it with the target's result). Host-call yields keep the placeholder (overwritten by `set_host_result`).
186 let event_yield = self.pending.event_wait_request;
187 let sub_call_yield = !self.pending_sync_frames.is_empty();
188 let child_yield = self.pending.waiting_for_children.is_some();
189 let host_yield = self.pending.host_call_request;
190 let val = if event_yield || sub_call_yield || child_yield || host_yield { Val::none() } else { self.pop().unwrap_or(Val::none()) };
191 self.resume_ip = if !event_yield && !sub_call_yield && !child_yield && !host_yield && ip < n && matches!(insns.get(ip), Some(ins) if ins.opcode == OpCode::PopTop) { ip + 1 } else { ip };
192 self.live_slots.truncate(slots_base);
193 // DON'T truncate exception_stack here, frames pushed in this exec belong to active try/except blocks; the enclosing `resume_coroutine` drains them into the coroutine's saved state so `try` survives the yield.
194 return Ok(val);
195 }
196 }
197 Ok(Some(v)) => {
198 self.live_slots.truncate(slots_base);
199 self.exception_stack.truncate(exc_base);
200 self.unwind_stack.truncate(unwind_base);
201 return Ok(v);
202 }

Callers 5

strptimeFunction · 0.80
exec_fromMethod · 0.80
exec_make_classMethod · 0.80
init_modulesMethod · 0.80
run_body_with_frameMethod · 0.80

Calls 15

takeMethod · 0.80
removeMethod · 0.80
ensure_fusedMethod · 0.80
ensure_const_valsMethod · 0.80
insertMethod · 0.80
fused_refMethod · 0.80
const_vals_refMethod · 0.80
pushMethod · 0.80
dispatchMethod · 0.80
is_noneMethod · 0.80
class_nameMethod · 0.80
lenMethod · 0.45

Tested by

no test coverage detected