Skip to content

Commit

Permalink
Fast convertion between static and non-static keys
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat committed May 1, 2023
1 parent bdf9bec commit 88ff904
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 46 deletions.
43 changes: 20 additions & 23 deletions boa_builtins/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,42 +50,42 @@ enum WellKnown {
}

#[derive(Debug, Clone, Eq)]
pub enum StaticPropertyKey<'a> {
String { value: &'a [u16], index: u16 },
pub enum StaticPropertyKey {
String { index: u16 },
Symbol(u8),
}

impl<'a> PartialEq for StaticPropertyKey<'a> {
impl PartialEq for StaticPropertyKey {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(
StaticPropertyKey::String { value: lhs, .. },
StaticPropertyKey::String { value: rhs, .. },
StaticPropertyKey::String { index: lhs, .. },
StaticPropertyKey::String { index: rhs, .. },
) => lhs == rhs,
(StaticPropertyKey::Symbol(lhs), StaticPropertyKey::Symbol(rhs)) => lhs == rhs,
_ => false,
}
}
}

impl<'a> Hash for StaticPropertyKey<'a> {
impl Hash for StaticPropertyKey {
fn hash<H: Hasher>(&self, state: &mut H) {
std::mem::discriminant(self).hash(state);
match self {
StaticPropertyKey::String { value, .. } => value.hash(state),
StaticPropertyKey::String { index } => index.hash(state),
StaticPropertyKey::Symbol(value) => value.hash(state),
}
}
}

impl PhfHash for StaticPropertyKey<'static> {
impl PhfHash for StaticPropertyKey {
#[inline]
fn phf_hash<H: Hasher>(&self, state: &mut H) {
self.hash(state)
}
}

impl FmtConst for StaticPropertyKey<'static> {
impl FmtConst for StaticPropertyKey {
fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if matches!(self, StaticPropertyKey::String { .. }) {
f.write_str("StaticPropertyKey::String(")?;
Expand All @@ -94,38 +94,37 @@ impl FmtConst for StaticPropertyKey<'static> {
}

match self {
StaticPropertyKey::String { value, index } => {
StaticPropertyKey::String { index } => {
write!(
f,
"/* {} */ RAW_STATICS[{}])",
String::from_utf16_lossy(value),
index
"/* */ {index})",
// String::from_utf16_lossy(value),
)
}
StaticPropertyKey::Symbol(s) => write!(f, "{})", s),
}
}
}

impl<'b, 'a: 'b> PhfBorrow<StaticPropertyKey<'b>> for StaticPropertyKey<'a> {
fn borrow(&self) -> &StaticPropertyKey<'b> {
impl PhfBorrow<StaticPropertyKey> for StaticPropertyKey {
fn borrow(&self) -> &StaticPropertyKey {
self
}
}

trait ToPropertyKey {
fn to_property_key(self, _context: &Context) -> StaticPropertyKey<'static>;
fn to_property_key(self, _context: &Context) -> StaticPropertyKey;
}

impl ToPropertyKey for &'static [u16] {
fn to_property_key(self, context: &Context) -> StaticPropertyKey<'static> {
fn to_property_key(self, context: &Context) -> StaticPropertyKey {
let index = context.insert_or_get(self);
StaticPropertyKey::String { value: self, index }
StaticPropertyKey::String { index }
}
}

impl ToPropertyKey for WellKnown {
fn to_property_key(self, _context: &Context) -> StaticPropertyKey<'static> {
fn to_property_key(self, _context: &Context) -> StaticPropertyKey {
StaticPropertyKey::Symbol(self as u8)
}
}
Expand Down Expand Up @@ -179,7 +178,7 @@ impl Context {
struct BuiltInBuilder<'a> {
context: &'a Context,
name: &'static str,
map: phf_codegen::OrderedMap<StaticPropertyKey<'static>>,
map: phf_codegen::OrderedMap<StaticPropertyKey>,
prototype: Option<&'static str>,

slot_index: usize,
Expand Down Expand Up @@ -371,9 +370,7 @@ impl<'a> BuiltInBuilderConstructor<'a> {
fn main() -> io::Result<()> {
// TODO: split into separate files
// TODO: Builtin slots are small, less than 256 properties, we could store the index and and attributes in an u16
// TODO: Generate a common static string table so all builtins can the table.
// - Instead of `StaticPropertyKey::String` holding a pointer hold an index into the static table
// TODO: With the two optimizations we could probably also store the property kind and index into a u16,
// TODO: we could probably store the property kind and index into a u16,
// every property entry being just a u32 value (u16 - property key, u16 - slot)

// TODO: because the generated static shapes for builtin file does not change that often and it's not that big,
Expand Down
30 changes: 15 additions & 15 deletions boa_builtins/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@ bitflags! {
}

#[derive(Clone, Copy, Eq)]
pub enum StaticPropertyKey<'a> {
String(&'a [u16]),
pub enum StaticPropertyKey {
String(u16),
Symbol(u8),
}

impl<'a> Debug for StaticPropertyKey<'a> {
impl Debug for StaticPropertyKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
StaticPropertyKey::String(string) => {
match *self {
StaticPropertyKey::String(index) => {
let string = RAW_STATICS[index as usize];
let string = String::from_utf16_lossy(string);
write!(f, "String(\"{string}\")")
}
Expand All @@ -42,7 +43,7 @@ impl<'a> Debug for StaticPropertyKey<'a> {
}
}

impl<'a> PartialEq for StaticPropertyKey<'a> {
impl PartialEq for StaticPropertyKey {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(StaticPropertyKey::String(lhs), StaticPropertyKey::String(rhs)) => lhs == rhs,
Expand All @@ -52,7 +53,7 @@ impl<'a> PartialEq for StaticPropertyKey<'a> {
}
}

impl<'a> Hash for StaticPropertyKey<'a> {
impl Hash for StaticPropertyKey {
fn hash<H: Hasher>(&self, state: &mut H) {
std::mem::discriminant(self).hash(state);
match self {
Expand All @@ -62,16 +63,16 @@ impl<'a> Hash for StaticPropertyKey<'a> {
}
}

impl PhfHash for StaticPropertyKey<'static> {
impl PhfHash for StaticPropertyKey {
#[inline]
fn phf_hash<H: Hasher>(&self, state: &mut H) {
self.hash(state)
}
}

impl<'b, 'a: 'b> PhfBorrow<StaticPropertyKey<'b>> for StaticPropertyKey<'a> {
impl PhfBorrow<StaticPropertyKey> for StaticPropertyKey {
#[inline]
fn borrow(&self) -> &StaticPropertyKey<'b> {
fn borrow(&self) -> &StaticPropertyKey {
self
}
}
Expand All @@ -80,7 +81,7 @@ pub type Slot = (u32, Attribute);

#[derive(Debug)]
pub struct StaticShape {
pub property_table: phf::OrderedMap<StaticPropertyKey<'static>, Slot>,
pub property_table: phf::OrderedMap<StaticPropertyKey, Slot>,

pub storage_len: usize,

Expand All @@ -90,11 +91,10 @@ pub struct StaticShape {

impl StaticShape {
#[inline]
pub fn get(&self, key: StaticPropertyKey<'_>) -> Option<Slot> {
pub fn get(&self, key: StaticPropertyKey) -> Option<Slot> {
// SAFETY: only used to extend the lifetime, so we are able to call get.
let key: &StaticPropertyKey<'static> = unsafe { std::mem::transmute(&key) };
self.property_table
.get(key)
.get(&key)
.map(|(index, attributes)| (*index, *attributes))
}

Expand All @@ -116,7 +116,7 @@ impl StaticShape {
.expect("there should be a key at the given index")
.0
{
StaticPropertyKey::String(s) => s,
StaticPropertyKey::String(index) => RAW_STATICS[*index as usize],
StaticPropertyKey::Symbol(s) => {
panic!("The key should be a string at position {index}, but symbol {s}")
}
Expand Down
18 changes: 10 additions & 8 deletions boa_engine/src/object/shape/static_shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use boa_gc::{Finalize, Trace};

use crate::{
object::shape::property_table::PropertyTableInner, property::PropertyKey, symbol::WellKnown,
JsSymbol,
JsString, JsSymbol,
};

use super::{
Expand All @@ -20,11 +20,13 @@ use super::{
pub(crate) type StaticShapeInner = &'static boa_builtins::StaticShape;

/// TODO: doc
fn from_static_property_key(key: &StaticPropertyKey<'_>) -> PropertyKey {
fn from_static_property_key(key: StaticPropertyKey) -> PropertyKey {
match key {
boa_builtins::StaticPropertyKey::String(s) => PropertyKey::from(*s),
boa_builtins::StaticPropertyKey::String(index) => {
PropertyKey::String(unsafe { JsString::from_index(index) })
}
boa_builtins::StaticPropertyKey::Symbol(s) => {
let symbol = match WellKnown::try_from(*s).expect("should be an well known symbol") {
let symbol = match WellKnown::try_from(s).expect("should be an well known symbol") {
WellKnown::AsyncIterator => JsSymbol::async_iterator(),
WellKnown::HasInstance => JsSymbol::has_instance(),
WellKnown::IsConcatSpreadable => JsSymbol::is_concat_spreadable(),
Expand All @@ -46,9 +48,9 @@ fn from_static_property_key(key: &StaticPropertyKey<'_>) -> PropertyKey {
}

/// TODO: doc
fn to_static_property_key(key: &PropertyKey) -> Option<StaticPropertyKey<'_>> {
fn to_static_property_key(key: &PropertyKey) -> Option<StaticPropertyKey> {
match key {
PropertyKey::String(s) => Some(StaticPropertyKey::String(s.as_slice())),
PropertyKey::String(s) => Some(StaticPropertyKey::String(s.as_static_string_index()?)),
PropertyKey::Symbol(s) => Some(StaticPropertyKey::Symbol(s.hash().try_into().ok()?)),
PropertyKey::Index(_) => None,
}
Expand Down Expand Up @@ -117,10 +119,10 @@ impl StaticShape {

/// Gets all keys first strings then symbols in creation order.
pub(crate) fn keys(&self) -> Vec<PropertyKey> {
dbg!(&self.inner.property_table);
self.inner
.property_table
.keys()
.copied()
.map(from_static_property_key)
.collect()
}
Expand All @@ -132,7 +134,7 @@ impl StaticShape {
let mut property_table = PropertyTableInner::default();
for (key, (_, slot_attributes)) in &self.inner.property_table {
property_table.insert(
from_static_property_key(key),
from_static_property_key(*key),
SlotAttributes::from_bits_retain(slot_attributes.bits()),
);
}
Expand Down
14 changes: 14 additions & 0 deletions boa_engine/src/string/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use crate::{
tagged::{Tagged, UnwrappedTagged},
JsBigInt,
};
use boa_builtins::RAW_STATICS_LEN;
use boa_gc::{empty_trace, Finalize, Trace};
pub use boa_macros::utf16;

Expand Down Expand Up @@ -617,6 +618,19 @@ impl JsString {
ptr: Tagged::from_non_null(ptr),
}
}

pub(crate) fn as_static_string_index(&self) -> Option<u16> {
if let UnwrappedTagged::Tag(index) = self.ptr.unwrap() {
return Some(index as u16);
}
None
}
pub(crate) const unsafe fn from_index(index: u16) -> JsString {
debug_assert!(index < RAW_STATICS_LEN);

Check failure on line 629 in boa_engine/src/string/mod.rs

View workflow job for this annotation

GitHub Actions / Coverage

mismatched types
JsString {
ptr: Tagged::from_tag(index as usize),
}
}
}

impl AsRef<[u16]> for JsString {
Expand Down

0 comments on commit 88ff904

Please sign in to comment.