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

1
boa_engine/Cargo.toml

@ -68,6 +68,7 @@ thiserror = "1.0.40"
dashmap = "5.4.0"
num_enum = "0.5.11"
pollster = "0.3.0"
thin-vec = "0.2.12"
# intl deps
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_parser::{Parser, Source};
use boa_profiler::Profiler;
use thin_vec::ThinVec;
use std::fmt;
@ -172,10 +173,10 @@ pub enum Function {
home_object: Option<JsObject>,
/// The `[[Fields]]` internal slot.
fields: Vec<ClassFieldDefinition>,
fields: ThinVec<ClassFieldDefinition>,
/// The `[[PrivateMethods]]` internal slot.
private_methods: Vec<(PrivateName, PrivateElement)>,
private_methods: ThinVec<(PrivateName, PrivateElement)>,
/// The class object that this function is associated with.
class_object: Option<JsObject>,
@ -238,7 +239,9 @@ unsafe impl Trace for Function {
mark(code);
mark(environments);
mark(home_object);
mark(fields);
for elem in fields {
mark(elem);
}
for (_, elem) in private_methods {
mark(elem);
}

3
boa_engine/src/object/jsobject.rs

@ -19,6 +19,7 @@ use std::{
fmt::{self, Debug, Display},
result::Result as StdResult,
};
use thin_vec::ThinVec;
/// A wrapper type for an immutably borrowed type T.
pub type Ref<'a, T> = boa_gc::GcRef<'a, T>;
@ -74,7 +75,7 @@ impl JsObject {
prototype: prototype.into(),
extensible: true,
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 operations::IntegrityLevel;
pub use property_map::*;
use thin_vec::ThinVec;
use self::internal_methods::{
arguments::ARGUMENTS_EXOTIC_INTERNAL_METHODS,
@ -128,7 +129,7 @@ pub struct Object {
/// Whether it can have new properties added to it.
extensible: bool,
/// The `[[PrivateElements]]` internal slot.
private_elements: Vec<(PrivateName, PrivateElement)>,
private_elements: ThinVec<(PrivateName, PrivateElement)>,
}
unsafe impl Trace for Object {
@ -782,7 +783,7 @@ impl Default for Object {
properties: PropertyMap::default(),
prototype: None,
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_profiler::Profiler;
use std::{collections::VecDeque, mem::size_of};
use thin_vec::ThinVec;
#[cfg(any(feature = "trace", feature = "flowgraph"))]
use crate::vm::Opcode;
@ -597,8 +598,8 @@ pub(crate) fn create_function_object(
environments: context.realm.environments.clone(),
constructor_kind: ConstructorKind::Base,
home_object: None,
fields: Vec::new(),
private_methods: Vec::new(),
fields: ThinVec::new(),
private_methods: ThinVec::new(),
class_object: None,
}
};

Loading…
Cancel
Save