Skip to content

Commit 98c3df2

Browse files
committed
Manage the stack a bit more efficiently
1 parent 9c895c2 commit 98c3df2

File tree

2 files changed

+43
-26
lines changed

2 files changed

+43
-26
lines changed

vm/src/frame.rs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -577,8 +577,9 @@ impl ExecutingFrame<'_> {
577577
bytecode::Instruction::BuildString { size } => {
578578
let s = self
579579
.pop_multiple(*size)
580-
.into_iter()
581-
.map(|pyobj| pystr::clone_value(&pyobj))
580+
.as_slice()
581+
.iter()
582+
.map(|pyobj| pystr::borrow_value(&pyobj))
582583
.collect::<String>();
583584
let str_obj = vm.ctx.new_str(s);
584585
self.push_value(str_obj);
@@ -591,10 +592,18 @@ impl ExecutingFrame<'_> {
591592
Ok(None)
592593
}
593594
bytecode::Instruction::BuildSet { size, unpack } => {
594-
let elements = self.get_elements(vm, *size, *unpack)?;
595595
let set = vm.ctx.new_set();
596-
for item in elements {
597-
set.add(item, vm)?;
596+
{
597+
let elements = self.pop_multiple(*size);
598+
if *unpack {
599+
for element in elements {
600+
vm.map_iterable_object(&element, |x| set.add(x, vm))??;
601+
}
602+
} else {
603+
for element in elements {
604+
set.add(element, vm)?;
605+
}
606+
}
598607
}
599608
self.push_value(set.into_object());
600609
Ok(None)
@@ -973,7 +982,7 @@ impl ExecutingFrame<'_> {
973982
}
974983
Ok(result)
975984
} else {
976-
Ok(elements)
985+
Ok(elements.collect())
977986
}
978987
}
979988

@@ -1173,7 +1182,7 @@ impl ExecutingFrame<'_> {
11731182
}
11741183
}
11751184
} else {
1176-
for (key, value) in self.pop_multiple(2 * size).into_iter().tuples() {
1185+
for (key, value) in self.pop_multiple(2 * size).tuples() {
11771186
map_obj.set_item(key, value, vm).unwrap();
11781187
}
11791188
}
@@ -1208,9 +1217,8 @@ impl ExecutingFrame<'_> {
12081217
vm: &VirtualMachine,
12091218
nargs: usize,
12101219
) -> FrameResult {
1211-
let args: Vec<PyObjectRef> = self.pop_multiple(nargs);
12121220
let args = FuncArgs {
1213-
args,
1221+
args: self.pop_multiple(nargs).collect(),
12141222
kwargs: IndexMap::new(),
12151223
};
12161224

@@ -1221,14 +1229,16 @@ impl ExecutingFrame<'_> {
12211229
}
12221230

12231231
fn execute_call_function_keyword(&mut self, vm: &VirtualMachine, nargs: usize) -> FrameResult {
1224-
let kwarg_names = self.pop_value();
1225-
let args: Vec<PyObjectRef> = self.pop_multiple(nargs);
1232+
let kwarg_names = self
1233+
.pop_value()
1234+
.downcast::<PyTuple>()
1235+
.expect("kwarg names should be tuple of strings");
1236+
let args = self.pop_multiple(nargs);
12261237

1227-
let kwarg_names = vm
1228-
.extract_elements(&kwarg_names)?
1238+
let kwarg_names = kwarg_names
1239+
.borrow_value()
12291240
.iter()
1230-
.map(|pyobj| pystr::clone_value(pyobj))
1231-
.collect();
1241+
.map(|pyobj| pystr::clone_value(pyobj));
12321242
let args = FuncArgs::with_kwargs_names(args, kwarg_names);
12331243

12341244
let func_ref = self.pop_value();
@@ -1665,12 +1675,9 @@ impl ExecutingFrame<'_> {
16651675
.expect("Tried to pop value but there was nothing on the stack")
16661676
}
16671677

1668-
fn pop_multiple(&mut self, count: usize) -> Vec<PyObjectRef> {
1678+
fn pop_multiple(&mut self, count: usize) -> std::vec::Drain<PyObjectRef> {
16691679
let stack_len = self.state.stack.len();
1670-
self.state
1671-
.stack
1672-
.drain(stack_len - count..stack_len)
1673-
.collect()
1680+
self.state.stack.drain(stack_len - count..stack_len)
16741681
}
16751682

16761683
fn last_value(&self) -> PyObjectRef {

vm/src/function.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::pyobject::{
88
};
99
use crate::vm::VirtualMachine;
1010
use indexmap::IndexMap;
11+
use itertools::Itertools;
1112
use result_like::impl_option_like;
1213
use std::collections::HashMap;
1314
use std::marker::PhantomData;
@@ -98,15 +99,24 @@ impl FuncArgs {
9899
Self { args, kwargs }
99100
}
100101

101-
pub fn with_kwargs_names(mut args: Vec<PyObjectRef>, kwarg_names: Vec<String>) -> Self {
102+
pub fn with_kwargs_names<A, KW>(mut args: A, kwarg_names: KW) -> Self
103+
where
104+
A: ExactSizeIterator<Item = PyObjectRef>,
105+
KW: ExactSizeIterator<Item = String>,
106+
{
102107
// last `kwarg_names.len()` elements of args in order of appearance in the call signature
103-
let kwarg_values = args.drain((args.len() - kwarg_names.len())..);
108+
let total_argc = args.len();
109+
let kwargc = kwarg_names.len();
110+
let posargc = total_argc - kwargc;
104111

105-
let mut kwargs = IndexMap::new();
106-
for (name, value) in kwarg_names.iter().zip(kwarg_values) {
107-
kwargs.insert(name.clone(), value);
112+
let posargs = args.by_ref().take(posargc).collect();
113+
114+
let kwargs = kwarg_names.zip_eq(args).collect::<IndexMap<_, _>>();
115+
116+
FuncArgs {
117+
args: posargs,
118+
kwargs,
108119
}
109-
FuncArgs { args, kwargs }
110120
}
111121

112122
pub fn prepend_arg(&mut self, item: PyObjectRef) {

0 commit comments

Comments
 (0)