Bladeren bron

Reference count inner data of AML buffer values

The inner data of buffers can be held and modified by both Buffer objects,
but also BufferField objects. I wonder if a good way of solving this neatly
would actually be to reference count this inner data, and hold Arcs to it
in both the parent buffer and any fields pointing into that buffer - let's
find out.
Isaac Woods 3 jaren geleden
bovenliggende
commit
f814fd61f8
3 gewijzigde bestanden met toevoegingen van 19 en 16 verwijderingen
  1. 4 3
      aml/src/resource.rs
  2. 12 10
      aml/src/type2.rs
  3. 3 3
      aml/src/value.rs

+ 4 - 3
aml/src/resource.rs

@@ -566,6 +566,7 @@ fn extended_interrupt_descriptor(bytes: &[u8]) -> Result<Resource, AmlError> {
 #[cfg(test)]
 mod tests {
     use super::*;
+    use std::sync::Arc;
 
     #[test]
     fn test_parses_keyboard_crs() {
@@ -599,7 +600,7 @@ mod tests {
         ]
         .to_vec();
 
-        let value: AmlValue = AmlValue::Buffer(bytes);
+        let value: AmlValue = AmlValue::Buffer(Arc::new(bytes));
         let resources = resource_descriptor_list(&value).unwrap();
 
         assert_eq!(
@@ -709,7 +710,7 @@ mod tests {
         ]
         .to_vec();
 
-        let value: AmlValue = AmlValue::Buffer(bytes);
+        let value: AmlValue = AmlValue::Buffer(Arc::new(bytes));
         let resources = resource_descriptor_list(&value).unwrap();
 
         assert_eq!(
@@ -810,7 +811,7 @@ mod tests {
         ]
         .to_vec();
 
-        let value: AmlValue = AmlValue::Buffer(bytes);
+        let value: AmlValue = AmlValue::Buffer(Arc::new(bytes));
         let resources = resource_descriptor_list(&value).unwrap();
 
         assert_eq!(

+ 12 - 10
aml/src/type2.rs

@@ -20,10 +20,11 @@ use crate::{
 };
 use alloc::{
     string::{String, ToString},
+    sync::Arc,
     vec,
     vec::Vec,
 };
-use core::{cmp::Ordering, convert::TryInto, mem};
+use core::{cmp::Ordering, convert::TryInto, mem, ops::Deref};
 
 /// Type 2 opcodes return a value and so can be used in expressions.
 pub fn type2_opcode<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
@@ -151,7 +152,7 @@ where
                 })
             }),
         ))
-        .map(|((), buffer)| Ok(AmlValue::Buffer(buffer)))
+        .map(|((), buffer)| Ok(AmlValue::Buffer(Arc::new(buffer))))
 }
 
 pub fn def_concat<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
@@ -175,11 +176,12 @@ where
                         buffer.extend_from_slice(&left.to_le_bytes());
                         buffer.extend_from_slice(&right.to_le_bytes());
 
-                        AmlValue::Buffer(buffer)
+                        AmlValue::Buffer(Arc::new(buffer))
                     }
-                    AmlValue::Buffer(mut left) => {
-                        left.extend(try_with_context!(context, right.as_buffer(context)));
-                        AmlValue::Buffer(left)
+                    AmlValue::Buffer(left) => {
+                        let mut new = left.deref().clone();
+                        new.extend(try_with_context!(context, right.as_buffer(context)).iter());
+                        AmlValue::Buffer(Arc::new(new))
                     }
                     AmlValue::String(left) => {
                         let right = match right.as_concat_type() {
@@ -246,7 +248,7 @@ where
                         result.iter().fold(0u8, |checksum, byte| checksum.wrapping_add(*byte)).wrapping_neg(),
                     );
 
-                    AmlValue::Buffer(result)
+                    AmlValue::Buffer(Arc::new(result))
                 };
 
                 try_with_context!(context, context.store(target, result.clone()));
@@ -417,11 +419,11 @@ where
                         match source {
                             AmlValue::Buffer(bytes) => {
                                 if index >= bytes.len() {
-                                    Ok(AmlValue::Buffer(vec![]))
+                                    Ok(AmlValue::Buffer(Arc::new(vec![])))
                                 } else if (index + length) >= bytes.len() {
-                                    Ok(AmlValue::Buffer(bytes[index..].to_vec()))
+                                    Ok(AmlValue::Buffer(Arc::new(bytes[index..].to_vec())))
                                 } else {
-                                    Ok(AmlValue::Buffer(bytes[index..(index + length)].to_vec()))
+                                    Ok(AmlValue::Buffer(Arc::new(bytes[index..(index + length)].to_vec())))
                                 }
                             }
                             /*

+ 3 - 3
aml/src/value.rs

@@ -197,7 +197,7 @@ pub enum AmlValue {
         flags: MethodFlags,
         code: MethodCode,
     },
-    Buffer(Vec<u8>),
+    Buffer(Arc<Vec<u8>>),
     Processor {
         id: u8,
         pblk_address: u32,
@@ -293,7 +293,7 @@ impl AmlValue {
         }
     }
 
-    pub fn as_buffer(&self, context: &AmlContext) -> Result<Vec<u8>, AmlError> {
+    pub fn as_buffer(&self, context: &AmlContext) -> Result<Arc<Vec<u8>>, AmlError> {
         match self {
             AmlValue::Buffer(ref bytes) => Ok(bytes.clone()),
             // TODO: implement conversion of String and Integer to Buffer
@@ -558,7 +558,7 @@ impl Args {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::{test_utils::*, AmlError};
+    use crate::test_utils::*;
     use core::cmp::Ordering;
 
     #[test]