浏览代码

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 年之前
父节点
当前提交
f814fd61f8
共有 3 个文件被更改,包括 19 次插入16 次删除
  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]