Skip to content

Commit 8fc678d

Browse files
committed
Add BinaryOpInplaceAddUnicode specialization
1 parent fa3af99 commit 8fc678d

File tree

1 file changed

+33
-11
lines changed

1 file changed

+33
-11
lines changed

crates/vm/src/frame.rs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,7 +1131,21 @@ impl ExecutingFrame<'_> {
11311131
// TODO: In CPython, this does in-place unicode concatenation when
11321132
// refcount is 1. Falls back to regular iadd for now.
11331133
Instruction::BinaryOpInplaceAddUnicode => {
1134-
self.execute_bin_op(vm, bytecode::BinaryOperator::InplaceAdd)
1134+
let b = self.top_value();
1135+
let a = self.nth_value(1);
1136+
if let (Some(a_str), Some(b_str)) = (
1137+
a.downcast_ref_if_exact::<PyStr>(vm),
1138+
b.downcast_ref_if_exact::<PyStr>(vm),
1139+
) {
1140+
let result = a_str.as_wtf8().py_add(b_str.as_wtf8());
1141+
self.pop_value();
1142+
self.pop_value();
1143+
self.push_value(result.to_pyobject(vm));
1144+
Ok(None)
1145+
} else {
1146+
self.deoptimize_binary_op(bytecode::BinaryOperator::InplaceAdd);
1147+
self.execute_bin_op(vm, bytecode::BinaryOperator::InplaceAdd)
1148+
}
11351149
}
11361150
Instruction::BinarySlice => {
11371151
// Stack: [container, start, stop] -> [result]
@@ -3139,15 +3153,11 @@ impl ExecutingFrame<'_> {
31393153
Ok(ch) => {
31403154
self.pop_value();
31413155
self.pop_value();
3142-
self.push_value(
3143-
PyStr::from(ch).into_pyobject(vm),
3144-
);
3156+
self.push_value(PyStr::from(ch).into_pyobject(vm));
31453157
return Ok(None);
31463158
}
31473159
Err(e) => {
3148-
self.deoptimize_binary_op(
3149-
bytecode::BinaryOperator::Subscr,
3150-
);
3160+
self.deoptimize_binary_op(bytecode::BinaryOperator::Subscr);
31513161
return Err(e);
31523162
}
31533163
}
@@ -3339,8 +3349,7 @@ impl ExecutingFrame<'_> {
33393349
let callable = self.pop_value();
33403350
let callable_tag = &*callable as *const PyObject as u32;
33413351
if cached_tag == callable_tag {
3342-
let elements: Vec<PyObjectRef> =
3343-
vm.extract_elements_with(&obj, Ok)?;
3352+
let elements: Vec<PyObjectRef> = vm.extract_elements_with(&obj, Ok)?;
33443353
self.push_value(vm.ctx.new_tuple(elements).into());
33453354
return Ok(None);
33463355
}
@@ -3590,7 +3599,9 @@ impl ExecutingFrame<'_> {
35903599
if elements.len() == size {
35913600
let elems: Vec<_> = elements.to_vec();
35923601
self.pop_value();
3593-
self.state.stack.extend(elems.into_iter().rev().map(Some));
3602+
for elem in elems.into_iter().rev() {
3603+
self.push_value(elem);
3604+
}
35943605
return Ok(None);
35953606
}
35963607
}
@@ -3606,7 +3617,9 @@ impl ExecutingFrame<'_> {
36063617
let elems: Vec<_> = vec.to_vec();
36073618
drop(vec);
36083619
self.pop_value();
3609-
self.state.stack.extend(elems.into_iter().rev().map(Some));
3620+
for elem in elems.into_iter().rev() {
3621+
self.push_value(elem);
3622+
}
36103623
return Ok(None);
36113624
}
36123625
}
@@ -5334,6 +5347,15 @@ impl ExecutingFrame<'_> {
53345347
None
53355348
}
53365349
}
5350+
bytecode::BinaryOperator::InplaceAdd => {
5351+
if a.downcast_ref_if_exact::<PyStr>(vm).is_some()
5352+
&& b.downcast_ref_if_exact::<PyStr>(vm).is_some()
5353+
{
5354+
Some(Instruction::BinaryOpInplaceAddUnicode)
5355+
} else {
5356+
None
5357+
}
5358+
}
53375359
_ => None,
53385360
};
53395361

0 commit comments

Comments
 (0)