Skip to content

Commit 41fd6cd

Browse files
committed
revert(strings): remove replacement-array overload
1 parent bc1619f commit 41fd6cd

10 files changed

Lines changed: 21 additions & 290 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,9 @@ frontend/source patterns may still reach a `Bridge/Exit` path even when an SSA i
761761
| `len(map)` | Bridge/Exit | Inline |
762762
| `get(map)` | Bridge/Exit | Helper |
763763
| `has(map)` | Bridge/Exit | Helper |
764+
| `string_contains`, `string_replace_literal`, `string_lower_ascii`, `string_split_literal` | Bridge/Exit | Helper |
765+
| `re::match`, `re::replace` | Bridge/Exit | Helper |
766+
| Dynamic `type`, `to_string`, equality, and `len` | Bridge/Exit | Helper (known `type` / string `to_string` cases are folded) |
764767
| All other builtins | Bridge/Exit | Bridge/Exit or NYI, depending on trace shape |
765768
| Host imports | Bridge/Exit | Bridge/Exit or branch-exit trace, never inline |
766769

src/builtins/runtime/core.rs

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -792,38 +792,6 @@ pub(crate) fn builtin_string_replace_literal_impl(
792792
text.replace(needle, replacement)
793793
}
794794

795-
/// Apply literal replacements in order from parallel `needles` and `replacements` arrays.
796-
///
797-
/// Each pair uses the same non-overlapping semantics as the scalar overload. Empty needles
798-
/// leave the current output unchanged. Both arrays must have equal length and contain strings.
799-
/// A length mismatch or a non-string element returns an error.
800-
#[pd_host_function(name = "string_replace_literal")]
801-
pub(crate) fn builtin_string_replace_literal_many_impl(
802-
text: VmStringRef<'_>,
803-
needles: VmArrayRef<'_>,
804-
replacements: VmArrayRef<'_>,
805-
) -> VmResult<String> {
806-
if needles.len() != replacements.len() {
807-
return Err(VmError::HostError(
808-
"string_replace_literal array lengths must match".to_string(),
809-
));
810-
}
811-
let mut out = text.to_string();
812-
for (needle, replacement) in needles.iter().zip(replacements.iter()) {
813-
let (Value::String(needle), Value::String(replacement)) = (needle, replacement) else {
814-
return Err(VmError::TypeMismatch("string arrays"));
815-
};
816-
if needle.is_empty() || out.contains(needle.as_str()) {
817-
out = builtin_string_replace_literal_impl(
818-
out.as_str(),
819-
needle.as_str(),
820-
replacement.as_str(),
821-
);
822-
}
823-
}
824-
Ok(out)
825-
}
826-
827795
/// Lower ASCII `A`-`Z` bytes in `text` while preserving UTF-8.
828796
#[pd_host_function(name = "string_lower_ascii")]
829797
pub(crate) fn builtin_string_lower_ascii_impl(text: VmStringRef<'_>) -> String {

src/builtins/runtime/mod.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,8 @@ pub(crate) fn execute_builtin_call(
7676
BuiltinFunction::MapIterClose => map_iter::close(vm, args).map(BuiltinCallOutcome::Return),
7777
BuiltinFunction::StringContains => core::builtin_string_contains(args)
7878
.map(IntoBuiltinCallOutcome::into_builtin_call_outcome),
79-
BuiltinFunction::StringReplaceLiteral => {
80-
if matches!(args, [Value::String(_), Value::Array(_), Value::Array(_)]) {
81-
core::builtin_string_replace_literal_many(args)
82-
.map(IntoBuiltinCallOutcome::into_builtin_call_outcome)
83-
} else {
84-
core::builtin_string_replace_literal(args)
85-
.map(IntoBuiltinCallOutcome::into_builtin_call_outcome)
86-
}
87-
}
79+
BuiltinFunction::StringReplaceLiteral => core::builtin_string_replace_literal(args)
80+
.map(IntoBuiltinCallOutcome::into_builtin_call_outcome),
8881
BuiltinFunction::StringLowerAscii => core::builtin_string_lower_ascii(args)
8982
.map(IntoBuiltinCallOutcome::into_builtin_call_outcome),
9083
BuiltinFunction::StringSplitLiteral => core::builtin_string_split_literal(args)

src/vm/jit/ir.rs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,6 @@ pub(crate) enum SsaInstKind {
156156
needle: SsaValueId,
157157
replacement: SsaValueId,
158158
},
159-
StringReplaceLiteralMany {
160-
text: SsaValueId,
161-
needles: SsaValueId,
162-
replacements: SsaValueId,
163-
},
164159
StringLowerAscii {
165160
text: SsaValueId,
166161
},
@@ -418,11 +413,6 @@ impl SsaInstKind {
418413
needle,
419414
replacement,
420415
} => vec![*text, *needle, *replacement],
421-
Self::StringReplaceLiteralMany {
422-
text,
423-
needles,
424-
replacements,
425-
} => vec![*text, *needles, *replacements],
426416
Self::StringLowerAscii { text } => vec![*text],
427417
Self::TypeOf { value } | Self::ToString { value } => vec![*value],
428418
Self::StringSplitLiteral { text, delimiter } => vec![*text, *delimiter],
@@ -1050,13 +1040,6 @@ fn render_inst_kind(kind: &SsaInstKind) -> String {
10501040
} => {
10511041
format!("string_replace_literal {text}, {needle}, {replacement}")
10521042
}
1053-
SsaInstKind::StringReplaceLiteralMany {
1054-
text,
1055-
needles,
1056-
replacements,
1057-
} => {
1058-
format!("string_replace_literal_many {text}, {needles}, {replacements}")
1059-
}
10601043
SsaInstKind::StringLowerAscii { text } => format!("string_lower_ascii {text}"),
10611044
SsaInstKind::TypeOf { value } => format!("type_of {value}"),
10621045
SsaInstKind::ToString { value } => format!("to_string {value}"),

src/vm/jit/native/lower.rs

Lines changed: 4 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,10 @@ use crate::vm::native::{
2626
shared_string_from_buffer_entry_address, sparse_restore_exit_signature,
2727
string_binary_transform_signature, string_contains_entry_address, string_contains_signature,
2828
string_lower_ascii_entry_address, string_replace_literal_entry_address,
29-
string_replace_literal_many_entry_address, string_replace_signature,
30-
string_split_literal_entry_address, string_unary_transform_signature, to_string_entry_address,
31-
type_of_entry_address, value_eq_entry_address, value_eq_signature, value_len_entry_address,
32-
value_len_signature, value_slot_signature, write_heap_value_to_slot_entry_address,
33-
zero_bytes_entry_address,
29+
string_replace_signature, string_split_literal_entry_address, string_unary_transform_signature,
30+
to_string_entry_address, type_of_entry_address, value_eq_entry_address, value_eq_signature,
31+
value_len_entry_address, value_len_signature, value_slot_signature,
32+
write_heap_value_to_slot_entry_address, zero_bytes_entry_address,
3433
};
3534
use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
3635
use cranelift_codegen::ir::immediates::Ieee64;
@@ -171,7 +170,6 @@ fn try_compile_ssa_trace(
171170
regex_match: regex_match_entry_address(),
172171
regex_replace: regex_replace_entry_address(),
173172
replace_literal: string_replace_literal_entry_address(),
174-
replace_literal_many: string_replace_literal_many_entry_address(),
175173
lower_ascii: string_lower_ascii_entry_address(),
176174
type_of: type_of_entry_address(),
177175
to_string: to_string_entry_address(),
@@ -501,7 +499,6 @@ struct SsaStringHelperAddrs {
501499
regex_match: usize,
502500
regex_replace: usize,
503501
replace_literal: usize,
504-
replace_literal_many: usize,
505502
lower_ascii: usize,
506503
type_of: usize,
507504
to_string: usize,
@@ -593,7 +590,6 @@ fn ssa_trace_supported(ssa: &SsaTrace) -> bool {
593590
| SsaInstKind::RegexMatch { .. }
594591
| SsaInstKind::RegexReplace { .. }
595592
| SsaInstKind::StringReplaceLiteral { .. }
596-
| SsaInstKind::StringReplaceLiteralMany { .. }
597593
| SsaInstKind::StringLowerAscii { .. }
598594
| SsaInstKind::TypeOf { .. }
599595
| SsaInstKind::ToString { .. }
@@ -877,7 +873,6 @@ fn ssa_inst_requires_owned_value_slot(kind: &SsaInstKind) -> bool {
877873
| SsaInstKind::StringGet { .. }
878874
| SsaInstKind::RegexReplace { .. }
879875
| SsaInstKind::StringReplaceLiteral { .. }
880-
| SsaInstKind::StringReplaceLiteralMany { .. }
881876
| SsaInstKind::StringLowerAscii { .. }
882877
| SsaInstKind::TypeOf { .. }
883878
| SsaInstKind::ToString { .. }
@@ -1831,41 +1826,6 @@ fn lower_ssa_inst(
18311826
ssa_store_heap_ptr_in_value(b, layout.value, out, layout.value.string_tag, out_raw);
18321827
out
18331828
}
1834-
SsaInstKind::StringReplaceLiteralMany {
1835-
text,
1836-
needles,
1837-
replacements,
1838-
} => {
1839-
let text = values[text];
1840-
let needles = values[needles];
1841-
let replacements = values[replacements];
1842-
let out_raw = ssa_call_string_replace_literal_many(
1843-
b,
1844-
pointer_type,
1845-
string_refs,
1846-
string_addrs,
1847-
text,
1848-
needles,
1849-
replacements,
1850-
)?;
1851-
let error = b.ins().icmp_imm(IntCC::Equal, out_raw, 0);
1852-
let failed = b.create_block();
1853-
let replaced = b.create_block();
1854-
b.ins().brif(error, failed, &[], replaced, &[]);
1855-
b.switch_to_block(failed);
1856-
let status = b.ins().iconst(types::I32, STATUS_ERROR as i64);
1857-
jump_with_status(b, exit_block, status);
1858-
b.switch_to_block(replaced);
1859-
let out = owned_value_temp_slot_addr(
1860-
b,
1861-
pointer_type,
1862-
owned_value_temps,
1863-
SsaTempValueSlotKey::Output(output.id),
1864-
)?;
1865-
clear_owned_value_temp_slot(b, pointer_type, helper_refs, helper_addrs, out)?;
1866-
ssa_store_heap_ptr_in_value(b, layout.value, out, layout.value.string_tag, out_raw);
1867-
out
1868-
}
18691829
SsaInstKind::StringReplaceLiteral {
18701830
text,
18711831
needle,
@@ -4025,24 +3985,6 @@ fn ssa_call_string_replace_literal(
40253985
Ok(b.inst_results(call)[0])
40263986
}
40273987

4028-
fn ssa_call_string_replace_literal_many(
4029-
b: &mut FunctionBuilder,
4030-
pointer_type: cranelift_codegen::ir::Type,
4031-
string_refs: SsaStringHelperRefs,
4032-
string_addrs: SsaStringHelperAddrs,
4033-
text: cranelift_codegen::ir::Value,
4034-
needles: cranelift_codegen::ir::Value,
4035-
replacements: cranelift_codegen::ir::Value,
4036-
) -> VmResult<cranelift_codegen::ir::Value> {
4037-
let helper_ptr = iconst_ptr_from_addr(b, pointer_type, string_addrs.replace_literal_many)?;
4038-
let call = b.ins().call_indirect(
4039-
string_refs.replace_ref,
4040-
helper_ptr,
4041-
&[text, needles, replacements],
4042-
);
4043-
Ok(b.inst_results(call)[0])
4044-
}
4045-
40463988
fn ssa_call_string_lower_ascii(
40473989
b: &mut FunctionBuilder,
40483990
pointer_type: cranelift_codegen::ir::Type,

src/vm/jit/recorder.rs

Lines changed: 9 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,6 @@ enum SpecializedBuiltinKind {
482482
RegexMatch,
483483
RegexReplace,
484484
StringReplaceLiteral,
485-
StringReplaceLiteralMany,
486485
StringLowerAscii,
487486
TypeOf,
488487
TypeOfKnown(ValueType),
@@ -1154,26 +1153,13 @@ pub(crate) fn record_trace(
11541153
.iter()
11551154
.all(|arg| arg.info.source_local != Some(local))
11561155
});
1157-
let replace_many = builtin == BuiltinFunction::StringReplaceLiteral
1158-
&& (operand_types(program, ip).1 == ValueType::Array
1159-
|| (args.get(1).is_some_and(|arg| {
1160-
observed_heap_container_kind(arg.info)
1161-
== Some(HeapContainerKind::Array)
1162-
}) && args.get(2).is_some_and(|arg| {
1163-
observed_heap_container_kind(arg.info)
1164-
== Some(HeapContainerKind::Array)
1165-
})));
1166-
let specialized_kind = if replace_many {
1167-
Some(SpecializedBuiltinKind::StringReplaceLiteralMany)
1168-
} else {
1169-
select_specialized_builtin_kind(
1170-
program,
1171-
ip,
1172-
builtin,
1173-
args[0].info,
1174-
container_was_moved,
1175-
)
1176-
};
1156+
let specialized_kind = select_specialized_builtin_kind(
1157+
program,
1158+
ip,
1159+
builtin,
1160+
args[0].info,
1161+
container_was_moved,
1162+
);
11771163
if let Some(kind) = specialized_kind {
11781164
let (name, out) = emit_specialized_builtin_call(
11791165
&mut builder,
@@ -2847,19 +2833,12 @@ fn analyze_specialized_builtin_call(
28472833
frame.push(ValueInfo::tagged_typed(ValueType::String));
28482834
Ok("regex_replace")
28492835
}
2850-
SpecializedBuiltinKind::StringReplaceLiteral
2851-
| SpecializedBuiltinKind::StringReplaceLiteralMany => {
2836+
SpecializedBuiltinKind::StringReplaceLiteral => {
28522837
let _ = frame.pop()?;
28532838
let _ = frame.pop()?;
28542839
let _ = frame.pop()?;
28552840
frame.push(ValueInfo::tagged_typed(ValueType::String));
2856-
Ok(
2857-
if matches!(kind, SpecializedBuiltinKind::StringReplaceLiteralMany) {
2858-
"string_replace_literal_many"
2859-
} else {
2860-
"string_replace_literal"
2861-
},
2862-
)
2841+
Ok("string_replace_literal")
28632842
}
28642843
SpecializedBuiltinKind::StringLowerAscii => {
28652844
let _ = frame.pop()?;
@@ -3296,28 +3275,6 @@ fn emit_specialized_builtin_call(
32963275
.map_err(|err| TraceRecordError::InvalidIr(err.to_string()))?;
32973276
Ok(("regex_replace", out))
32983277
}
3299-
SpecializedBuiltinKind::StringReplaceLiteralMany => {
3300-
let replacements = ensure_heap_ptr(builder, block, ip, frame.pop()?, ValueType::Array)?;
3301-
let needles = ensure_heap_ptr(builder, block, ip, frame.pop()?, ValueType::Array)?;
3302-
let text = ensure_heap_ptr(builder, block, ip, frame.pop()?, ValueType::String)?;
3303-
let value = builder
3304-
.append_value_inst(
3305-
block,
3306-
ip,
3307-
SsaValueRepr::Tagged,
3308-
SsaInstKind::StringReplaceLiteralMany {
3309-
text: text.value.id,
3310-
needles: needles.value.id,
3311-
replacements: replacements.value.id,
3312-
},
3313-
)
3314-
.map(|value| SymbolicValue {
3315-
value,
3316-
info: ValueInfo::tagged_typed(ValueType::String),
3317-
})
3318-
.map_err(|err| TraceRecordError::InvalidIr(err.to_string()))?;
3319-
Ok(("string_replace_literal_many", value))
3320-
}
33213278
SpecializedBuiltinKind::StringReplaceLiteral => {
33223279
let replacement = ensure_heap_ptr(
33233280
builder,

src/vm/native/bridge.rs

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,6 @@ pub(crate) fn string_replace_literal_entry_address() -> usize {
215215
pd_vm_native_string_replace_literal as *const () as usize
216216
}
217217

218-
pub(crate) fn string_replace_literal_many_entry_address() -> usize {
219-
pd_vm_native_string_replace_literal_many as *const () as usize
220-
}
221-
222218
pub(crate) fn string_lower_ascii_entry_address() -> usize {
223219
pd_vm_native_string_lower_ascii as *const () as usize
224220
}
@@ -502,29 +498,6 @@ pub(crate) extern "C" fn pd_vm_native_string_replace_literal(
502498
))
503499
}
504500

505-
pub(crate) extern "C" fn pd_vm_native_string_replace_literal_many(
506-
text_ptr: *mut u8,
507-
needles_ptr: *mut u8,
508-
replacements_ptr: *mut u8,
509-
) -> *mut u8 {
510-
let text = unsafe { std::mem::ManuallyDrop::new(arc_from_repr_ptr::<String>(text_ptr)) };
511-
let needles =
512-
unsafe { std::mem::ManuallyDrop::new(arc_from_repr_ptr::<Vec<Value>>(needles_ptr)) };
513-
let replacements =
514-
unsafe { std::mem::ManuallyDrop::new(arc_from_repr_ptr::<Vec<Value>>(replacements_ptr)) };
515-
match crate::builtins::runtime::core::builtin_string_replace_literal_many_impl(
516-
text.as_str(),
517-
needles.as_slice(),
518-
replacements.as_slice(),
519-
) {
520-
Ok(value) => arc_into_repr_ptr(Arc::new(value)),
521-
Err(error) => {
522-
store_bridge_error(error);
523-
std::ptr::null_mut()
524-
}
525-
}
526-
}
527-
528501
pub(crate) extern "C" fn pd_vm_native_string_lower_ascii(text_ptr: *mut u8) -> *mut u8 {
529502
let text = unsafe { std::mem::ManuallyDrop::new(arc_from_repr_ptr::<String>(text_ptr)) };
530503
arc_into_repr_ptr(Arc::new(

src/vm/native/mod.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@ pub(crate) use bridge::{
2121
restore_sparse_exit_state_entry_address, shared_array_from_buffer_entry_address,
2222
shared_bytes_from_buffer_entry_address, shared_string_from_buffer_entry_address,
2323
store_bridge_error, string_contains_entry_address, string_lower_ascii_entry_address,
24-
string_replace_literal_entry_address, string_replace_literal_many_entry_address,
25-
string_split_literal_entry_address, take_bridge_error, to_string_entry_address,
26-
type_of_entry_address, value_eq_entry_address, value_len_entry_address,
27-
write_heap_value_to_slot_entry_address, zero_bytes_entry_address,
24+
string_replace_literal_entry_address, string_split_literal_entry_address, take_bridge_error,
25+
to_string_entry_address, type_of_entry_address, value_eq_entry_address,
26+
value_len_entry_address, write_heap_value_to_slot_entry_address, zero_bytes_entry_address,
2827
};
2928
#[cfg(feature = "cranelift-jit")]
3029
pub(crate) use codegen::{

stdlib/tests/strings.rss

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ assert(contains("hello", "ell"));
1010
assert(contains("hello", "zzz") == false);
1111
assert(equals(trim(" rustscript\n"), "rustscript"));
1212
assert(equals(replace("go gopher go", "go", "rs"), "rs rspher rs"));
13-
assert(equals(
14-
string_replace_literal("%27x%20y+z", ["%27", "%20", "+"], ["'", " ", " "]),
15-
"'x y z"
16-
));
1713

1814
let mut parts = split("a,b,c", ",");
1915
assert(parts.length == 3);

0 commit comments

Comments
 (0)