From 66d1f30b5a5dab9a607f8af0f728b6b0686897dc Mon Sep 17 00:00:00 2001 From: imxyy_soope_ Date: Wed, 29 Apr 2026 18:11:26 +0800 Subject: [PATCH] temp --- fix-codegen/src/lib.rs | 15 +++----- fix-vm/src/bytecode_reader.rs | 8 ++-- fix-vm/src/instructions/arithmetic.rs | 2 + fix-vm/src/instructions/builtins.rs | 8 ++-- fix-vm/src/instructions/collections.rs | 8 ++-- fix-vm/src/lib.rs | 6 +-- fix-vm/src/value.rs | 51 ++++++++++++++++---------- 7 files changed, 55 insertions(+), 43 deletions(-) diff --git a/fix-codegen/src/lib.rs b/fix-codegen/src/lib.rs index 38dc8aa..af8841e 100644 --- a/fix-codegen/src/lib.rs +++ b/fix-codegen/src/lib.rs @@ -164,7 +164,7 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> { } #[must_use] - fn inline_maybe_thunk(&mut self, val: MaybeThunk) -> InlineOperand { + fn inline_maybe_thunk(&self, val: MaybeThunk) -> InlineOperand { use MaybeThunk::*; match val { Int(x) => { @@ -812,14 +812,11 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> { let span_id = self.ctx.register_span(span); self.emit_u32(span_id); } - for &(_key, _val, _span) in dyns.iter() { - todo!("redesign dynamic attr key"); - // self.emit_u8(AttrKeyType::Dynamic as u8); - // self.emit_maybe_thunk(key); - // let val_operand = self.inline_maybe_thunk(val); - // self.emit_maybe_thunk(val); - // let span_id = self.ctx.register_span(span); - // self.emit_u32(span_id); + for &(_key, val, span) in dyns.iter() { + self.emit_u8(AttrKeyType::Dynamic as u8); + self.emit_maybe_thunk(val); + let span_id = self.ctx.register_span(span); + self.emit_u32(span_id); } } diff --git a/fix-vm/src/bytecode_reader.rs b/fix-vm/src/bytecode_reader.rs index 12091c0..abe35f8 100644 --- a/fix-vm/src/bytecode_reader.rs +++ b/fix-vm/src/bytecode_reader.rs @@ -3,7 +3,7 @@ use fix_common::StringId; use num_enum::TryFromPrimitive; use string_interner::Symbol as _; -use crate::{OperandData, VmRuntimeCtx}; +use crate::{AttrKeyData, OperandData, VmRuntimeCtx}; pub(crate) struct BytecodeReader<'a> { bytecode: &'a [u8], @@ -117,14 +117,14 @@ impl<'a> BytecodeReader<'a> { } #[inline(always)] - pub(crate) fn read_attr_key_data(&mut self, ctx: &C) -> crate::AttrKeyData { + pub(crate) fn read_attr_key_data(&mut self) -> crate::AttrKeyData { use fix_codegen::AttrKeyType; let tag = self.read_u8(); let ty = AttrKeyType::try_from_primitive(tag) .unwrap_or_else(|err| panic!("unknown key tag: {:#04x}", err.number)); match ty { - AttrKeyType::Static => crate::AttrKeyData::Static(self.read_string_id()), - AttrKeyType::Dynamic => crate::AttrKeyData::Dynamic(self.read_operand_data(ctx)), + AttrKeyType::Static => AttrKeyData::Static(self.read_string_id()), + AttrKeyType::Dynamic => AttrKeyData::Dynamic, } } diff --git a/fix-vm/src/instructions/arithmetic.rs b/fix-vm/src/instructions/arithmetic.rs index 2cb080a..12dc9c7 100644 --- a/fix-vm/src/instructions/arithmetic.rs +++ b/fix-vm/src/instructions/arithmetic.rs @@ -249,6 +249,8 @@ impl<'gc> crate::Vm<'gc> { return Ok(true); } if let (Some(a), Some(b)) = (lhs.as_gc::(), rhs.as_gc::()) { + let a = a.entries.borrow(); + let b = b.entries.borrow(); if a.len() != b.len() { return Ok(false); } diff --git a/fix-vm/src/instructions/builtins.rs b/fix-vm/src/instructions/builtins.rs index a86d1d0..7a122ac 100644 --- a/fix-vm/src/instructions/builtins.rs +++ b/fix-vm/src/instructions/builtins.rs @@ -165,6 +165,7 @@ impl<'gc> Vm<'gc> { let e1 = self.peek_forced(1); let children: SmallVec<_> = if let Some(attrs) = e1.as_gc::() { + let attrs = attrs.entries.borrow(); if attrs.is_empty() { SmallVec::new() } else { @@ -242,6 +243,7 @@ impl<'gc> Vm<'gc> { let mut added: usize = 0; if let Some(attrs) = item.as_gc::() { + let attrs = attrs.entries.borrow(); #[allow(clippy::unwrap_used)] let seen = self.peek_forced(2).as_gc::>().unwrap(); if !self.is_value_in_seen(seen, item) { @@ -289,7 +291,7 @@ impl<'gc> Vm<'gc> { let val = self.peek_forced(0); let (count, has_children) = if let Some(attrs) = val.as_gc::() { - let len = attrs.len(); + let len = attrs.entries.borrow().len(); (len, len > 0) } else if let Some(list) = val.as_gc::>() { let len = list.inner.borrow().len(); @@ -329,7 +331,7 @@ impl<'gc> Vm<'gc> { let val = self.peek_forced(2); let child = if let Some(attrs) = val.as_gc::() { - attrs.get(idx as usize).map(|&(_, v)| v) + attrs.entries.borrow().get(idx as usize).map(|&(_, v)| v) } else if let Some(list) = val.as_gc::>() { list.inner.borrow().get(idx as usize).copied() } else { @@ -398,7 +400,7 @@ impl<'gc> Vm<'gc> { ))); } } - for &(key, _) in attrset.iter() { + for &(key, _) in attrset.entries.borrow().iter() { let is_expected = pattern.required.contains(&key) || pattern.optional.contains(&key); if !is_expected { diff --git a/fix-vm/src/instructions/collections.rs b/fix-vm/src/instructions/collections.rs index 37be42f..96497e1 100644 --- a/fix-vm/src/instructions/collections.rs +++ b/fix-vm/src/instructions/collections.rs @@ -20,7 +20,7 @@ impl<'gc> crate::Vm<'gc> { let count = reader.read_u32() as usize; let mut entries: SmallVec<[AttrEntry; 4]> = SmallVec::with_capacity(count); for _ in 0..count { - let key = reader.read_attr_key_data(ctx); + let key = reader.read_attr_key_data(); let val = reader.read_operand_data(ctx); let _span_id = reader.read_u32(); entries.push(AttrEntry { key, val }); @@ -29,10 +29,8 @@ impl<'gc> crate::Vm<'gc> { for entry in &entries { let key_sid = match &entry.key { AttrKeyData::Static(sid) => *sid, - AttrKeyData::Dynamic(op) => { - let v = op.resolve(mc, self); - v.as_inline::() - .expect("dynamic attr key must be a string") + AttrKeyData::Dynamic => { + todo!() } }; let val = entry.val.resolve(mc, self); diff --git a/fix-vm/src/lib.rs b/fix-vm/src/lib.rs index ac2fd4f..58bbaaf 100644 --- a/fix-vm/src/lib.rs +++ b/fix-vm/src/lib.rs @@ -143,14 +143,14 @@ impl ConvertValueWithSeen for T { Value::String(ns.as_str().to_owned()) } else if let Some(attrs) = val.as_gc::() { let bits = val.to_bits(); - if attrs.is_empty() { + if attrs.entries.borrow().is_empty() { return Value::AttrSet(Default::default()); } if !seen.insert(bits) { return Value::Repeated; } let mut map = std::collections::BTreeMap::new(); - for &(key, val) in attrs.iter() { + for &(key, val) in attrs.entries.borrow().iter() { let key = self.resolve_string(key).to_owned(); let converted = self.convert_value_with_seen(val, seen); map.insert(fix_common::Symbol::from(key), converted); @@ -252,7 +252,7 @@ impl OperandData { pub(crate) enum AttrKeyData { Static(StringId), - Dynamic(OperandData), + Dynamic, } fn init_builtins<'gc>(mc: &Mutation<'gc>, ctx: &mut impl VmRuntimeCtx) -> Value<'gc> { diff --git a/fix-vm/src/value.rs b/fix-vm/src/value.rs index 704f29a..a55c052 100644 --- a/fix-vm/src/value.rs +++ b/fix-vm/src/value.rs @@ -435,65 +435,78 @@ impl fmt::Debug for NixString { #[derive(Collect, Debug, Default)] #[collect(no_drop)] pub(crate) struct AttrSet<'gc> { - entries: SmallVec<[(StringId, Value<'gc>); 4]>, + pub(crate) entries: RefLock); 4]>>, } -impl<'gc> Deref for AttrSet<'gc> { - type Target = [(StringId, Value<'gc>)]; - fn deref(&self) -> &Self::Target { - &self.entries +impl<'gc> Unlock for AttrSet<'gc> { + type Unlocked = RefCell); 4]>>; + unsafe fn unlock_unchecked(&self) -> &Self::Unlocked { + unsafe { self.entries.unlock_unchecked() } } } impl<'gc> AttrSet<'gc> { pub(crate) fn from_sorted_unchecked(entries: SmallVec<[(StringId, Value<'gc>); 4]>) -> Self { debug_assert!(entries.is_sorted_by_key(|(key, _)| *key)); - Self { entries } + Self { + entries: RefLock::new(entries), + } } pub(crate) fn lookup(&self, key: StringId) -> Option> { - self.entries + let entries = self.entries.borrow(); + entries .binary_search_by_key(&key, |(k, _)| *k) .ok() - .map(|i| self.entries[i].1) + .map(|i| entries[i].1) } pub(crate) fn has(&self, key: StringId) -> bool { - self.entries.binary_search_by_key(&key, |(k, _)| *k).is_ok() + self.entries + .borrow() + .binary_search_by_key(&key, |(k, _)| *k) + .is_ok() } pub(crate) fn merge(&self, other: &Self, mc: &Mutation<'gc>) -> Gc<'gc, Self> { use std::cmp::Ordering::*; - debug_assert!(self.entries.is_sorted_by_key(|(key, _)| *key)); - debug_assert!(other.entries.is_sorted_by_key(|(key, _)| *key)); + let self_entries = self.entries.borrow(); + let other_entries = other.entries.borrow(); + debug_assert!(self_entries.is_sorted_by_key(|(key, _)| *key)); + debug_assert!(other_entries.is_sorted_by_key(|(key, _)| *key)); let mut entries = SmallVec::new(); let mut i = 0; let mut j = 0; - while i < self.entries.len() && j < other.entries.len() { - match self.entries[i].0.cmp(&other.entries[j].0) { + while i < self_entries.len() && j < other_entries.len() { + match self_entries[i].0.cmp(&other_entries[j].0) { Less => { - entries.push(self.entries[i]); + entries.push(self_entries[i]); i += 1; } Greater => { - entries.push(other.entries[j]); + entries.push(other_entries[j]); j += 1; } Equal => { - entries.push(other.entries[j]); + entries.push(other_entries[j]); i += 1; j += 1; } } } - entries.extend(other.entries[j..].iter().cloned()); - entries.extend(self.entries[i..].iter().cloned()); + entries.extend(other_entries[j..].iter().cloned()); + entries.extend(self_entries[i..].iter().cloned()); debug_assert!(entries.is_sorted_by_key(|(key, _)| *key)); - Gc::new(mc, AttrSet { entries }) + Gc::new( + mc, + AttrSet { + entries: RefLock::new(entries), + }, + ) } }