Browse Source

Shrink objects by using `ThinVec`s (#2752)

The fields like `[[PrivateElements]]` are hardly used but they occupy `24` bytes (on 64-bit arch.) the `ThinVec` type stores the `len` and `cap` right before the elements (like our `JsString` implementation) and only a pointer is kept (if not used it does not allocate!), was going to use this in #2723 , since it uses a `Vec` as a dense storage, but the PR is already too big.

It changes the following:

- Shrink object from `328` to `288` bytes (40 bytes reduction)
- Add the `thin_vec` lightweight crate (single file)
pull/2754/head
Haled Odat 2 years ago
parent
commit
ed358dea0c
  1. 7
      Cargo.lock
  2. 1
      boa_engine/Cargo.toml
  3. 9
      boa_engine/src/builtins/function/mod.rs
  4. 3
      boa_engine/src/object/jsobject.rs
  5. 5
      boa_engine/src/object/mod.rs
  6. 5
      boa_engine/src/vm/code_block.rs

7
Cargo.lock generated

@ -373,6 +373,7 @@ dependencies = [
"sys-locale", "sys-locale",
"tap", "tap",
"textwrap 0.16.0", "textwrap 0.16.0",
"thin-vec",
"thiserror", "thiserror",
"unicode-normalization", "unicode-normalization",
"writeable", "writeable",
@ -3984,6 +3985,12 @@ dependencies = [
"unicode-width", "unicode-width",
] ]
[[package]]
name = "thin-vec"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aac81b6fd6beb5884b0cf3321b8117e6e5d47ecb6fc89f414cfdcca8b2fe2dd8"
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.40" version = "1.0.40"

1
boa_engine/Cargo.toml

@ -68,6 +68,7 @@ thiserror = "1.0.40"
dashmap = "5.4.0" dashmap = "5.4.0"
num_enum = "0.5.11" num_enum = "0.5.11"
pollster = "0.3.0" pollster = "0.3.0"
thin-vec = "0.2.12"
# intl deps # intl deps
boa_icu_provider = { workspace = true, optional = true } boa_icu_provider = { workspace = true, optional = true }

9
boa_engine/src/builtins/function/mod.rs

@ -36,6 +36,7 @@ use boa_gc::{self, custom_trace, Finalize, Gc, Trace};
use boa_interner::Sym; use boa_interner::Sym;
use boa_parser::{Parser, Source}; use boa_parser::{Parser, Source};
use boa_profiler::Profiler; use boa_profiler::Profiler;
use thin_vec::ThinVec;
use std::fmt; use std::fmt;
@ -172,10 +173,10 @@ pub enum Function {
home_object: Option<JsObject>, home_object: Option<JsObject>,
/// The `[[Fields]]` internal slot. /// The `[[Fields]]` internal slot.
fields: Vec<ClassFieldDefinition>, fields: ThinVec<ClassFieldDefinition>,
/// The `[[PrivateMethods]]` internal slot. /// The `[[PrivateMethods]]` internal slot.
private_methods: Vec<(PrivateName, PrivateElement)>, private_methods: ThinVec<(PrivateName, PrivateElement)>,
/// The class object that this function is associated with. /// The class object that this function is associated with.
class_object: Option<JsObject>, class_object: Option<JsObject>,
@ -238,7 +239,9 @@ unsafe impl Trace for Function {
mark(code); mark(code);
mark(environments); mark(environments);
mark(home_object); mark(home_object);
mark(fields); for elem in fields {
mark(elem);
}
for (_, elem) in private_methods { for (_, elem) in private_methods {
mark(elem); mark(elem);
} }

3
boa_engine/src/object/jsobject.rs

@ -19,6 +19,7 @@ use std::{
fmt::{self, Debug, Display}, fmt::{self, Debug, Display},
result::Result as StdResult, result::Result as StdResult,
}; };
use thin_vec::ThinVec;
/// A wrapper type for an immutably borrowed type T. /// A wrapper type for an immutably borrowed type T.
pub type Ref<'a, T> = boa_gc::GcRef<'a, T>; pub type Ref<'a, T> = boa_gc::GcRef<'a, T>;
@ -74,7 +75,7 @@ impl JsObject {
prototype: prototype.into(), prototype: prototype.into(),
extensible: true, extensible: true,
properties: PropertyMap::default(), properties: PropertyMap::default(),
private_elements: Vec::new(), private_elements: ThinVec::new(),
})), })),
} }
} }

5
boa_engine/src/object/mod.rs

@ -6,6 +6,7 @@ use boa_ast::function::PrivateName;
pub use jsobject::{RecursionLimiter, Ref, RefMut}; pub use jsobject::{RecursionLimiter, Ref, RefMut};
pub use operations::IntegrityLevel; pub use operations::IntegrityLevel;
pub use property_map::*; pub use property_map::*;
use thin_vec::ThinVec;
use self::internal_methods::{ use self::internal_methods::{
arguments::ARGUMENTS_EXOTIC_INTERNAL_METHODS, arguments::ARGUMENTS_EXOTIC_INTERNAL_METHODS,
@ -128,7 +129,7 @@ pub struct Object {
/// Whether it can have new properties added to it. /// Whether it can have new properties added to it.
extensible: bool, extensible: bool,
/// The `[[PrivateElements]]` internal slot. /// The `[[PrivateElements]]` internal slot.
private_elements: Vec<(PrivateName, PrivateElement)>, private_elements: ThinVec<(PrivateName, PrivateElement)>,
} }
unsafe impl Trace for Object { unsafe impl Trace for Object {
@ -782,7 +783,7 @@ impl Default for Object {
properties: PropertyMap::default(), properties: PropertyMap::default(),
prototype: None, prototype: None,
extensible: true, extensible: true,
private_elements: Vec::default(), private_elements: ThinVec::default(),
} }
} }
} }

5
boa_engine/src/vm/code_block.rs

@ -29,6 +29,7 @@ use boa_gc::{Finalize, Gc, GcRefCell, Trace};
use boa_interner::Sym; use boa_interner::Sym;
use boa_profiler::Profiler; use boa_profiler::Profiler;
use std::{collections::VecDeque, mem::size_of}; use std::{collections::VecDeque, mem::size_of};
use thin_vec::ThinVec;
#[cfg(any(feature = "trace", feature = "flowgraph"))] #[cfg(any(feature = "trace", feature = "flowgraph"))]
use crate::vm::Opcode; use crate::vm::Opcode;
@ -597,8 +598,8 @@ pub(crate) fn create_function_object(
environments: context.realm.environments.clone(), environments: context.realm.environments.clone(),
constructor_kind: ConstructorKind::Base, constructor_kind: ConstructorKind::Base,
home_object: None, home_object: None,
fields: Vec::new(), fields: ThinVec::new(),
private_methods: Vec::new(), private_methods: ThinVec::new(),
class_object: None, class_object: None,
} }
}; };

Loading…
Cancel
Save