perf: 字符串 +/+= 二元拼接改 Cons rope 惰性扁平化消除 O(n²)

JsString 拆 Flat/Cons 变体:Cons 经独立 ConsNode 保存左右子节点 + O(1)
字节长 + 惰性扁平化产物缓存(OnceLock 原子发布,产物挂节点生命周期)。
concat_strings 接线:总长 ≤ 128B 的小链急切扁平(与 rope 前同款,拼接即
消费场景零开销),大链 O(1) 链接——大段重复拼接从 O(n²) 拷贝降为 O(n)
链接,文本在消费点(.length/==/string_ref/方法族)首次扁平化后缓存。

GC 兼容:mark 收口 mark_string_live 传播 Cons 子节点与产物闭包(显式栈
防深链爆栈);sweep/full_reset 共用 drop 辅助连带释放产物;节点字节记账
用 O(1) byte_len。rope 节点登记 session 字符串表,与执行期字符串 GC
(指令边界触发)天然兼容。JsString 结构 32B 与 rope 前同 bin,小串路径
零结构回退;unsafe impl Send/Sync 论证同 StringPtr(perm 恒 Flat)。
This commit is contained in:
2026-08-15 14:32:08 +08:00
parent 517aef7fba
commit 350b65c091
15 changed files with 737 additions and 63 deletions
+6 -6
View File
@@ -151,7 +151,7 @@ impl Vm {
let val = self.regs[reg];
let s = if val.is_string() {
// SAFETY: val 是字符串值。
unsafe { (*val.as_string_ptr()).data.clone() }
unsafe { (*val.as_string_ptr()).to_owned_string() }
} else {
to_string_full(val, self)?
};
@@ -163,7 +163,7 @@ impl Vm {
let val = imm[const_idx];
if val.is_string() {
// SAFETY: val 是字符串值。
let s = unsafe { (*val.as_string_ptr()).data.clone() };
let s = unsafe { (*val.as_string_ptr()).to_owned_string() };
result.push_str(&s);
}
}
@@ -684,7 +684,7 @@ impl Vm {
JsValue::from_js_object(proto_ptr),
));
if src.is_string() {
let code_units: Vec<u16> = unsafe { (*src.as_string_ptr()).data.encode_utf16().collect() };
let code_units: Vec<u16> = unsafe { (*src.as_string_ptr()).as_str().encode_utf16().collect() };
for (i, unit) in code_units.iter().enumerate() {
let si = make_int_key(i as u32);
let ch_val = match char::from_u32(*unit as u32) {
@@ -707,7 +707,7 @@ impl Vm {
.and_then(|v| {
if v.is_string() {
// SAFETY: v 是字符串常量值。
Some(unsafe { (*v.as_string_ptr()).data.clone() })
Some(unsafe { (*v.as_string_ptr()).to_owned_string() })
} else {
None
}
@@ -742,7 +742,7 @@ impl Vm {
// 字符串包装对象:索引字符是可枚举自有属性(ToObject("str") 的 0..len-1)。
if src_obj.type_tag == JsObject::OBJ_TYPE_STRING_OBJ {
let raw = src_obj.get_prop_at(0);
let s = unsafe { (*raw.as_string_ptr()).data.clone() };
let s = unsafe { (*raw.as_string_ptr()).to_owned_string() };
let code_units: Vec<u16> = s.encode_utf16().collect();
for (i, unit) in code_units.iter().enumerate() {
let si = make_int_key(i as u32);
@@ -850,7 +850,7 @@ impl Vm {
// 字符串源:按索引复制字符(可枚举索引属性)。
if src.is_string() {
let target = unsafe { &mut *target_val.as_js_object_ptr() };
let code_units: Vec<u16> = unsafe { (*src.as_string_ptr()).data.encode_utf16().collect() };
let code_units: Vec<u16> = unsafe { (*src.as_string_ptr()).as_str().encode_utf16().collect() };
for (i, unit) in code_units.iter().enumerate() {
let si = make_int_key(i as u32);
let ch_val = match char::from_u32(*unit as u32) {