Skip to content

Commit

Permalink
Merge cfd3542 into e81e06b
Browse files Browse the repository at this point in the history
  • Loading branch information
jedel1043 authored Jun 28, 2022
2 parents e81e06b + cfd3542 commit b1f06a6
Show file tree
Hide file tree
Showing 12 changed files with 424 additions and 308 deletions.
37 changes: 3 additions & 34 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions boa_engine/src/bytecompiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::{
vm::{BindingOpcode, CodeBlock, Opcode},
Context, JsBigInt, JsResult, JsString, JsValue,
};
use boa_gc::{Cell, Gc};
use boa_gc::Gc;
use boa_interner::{Interner, Sym};
use rustc_hash::FxHashMap;
use std::mem::size_of;
Expand Down Expand Up @@ -97,7 +97,10 @@ impl<'b> ByteCompiler<'b> {

/// Push a compile time environment to the current `CodeBlock` and return it's index.
#[inline]
fn push_compile_environment(&mut self, environment: Gc<Cell<CompileTimeEnvironment>>) -> usize {
fn push_compile_environment(
&mut self,
environment: Gc<boa_gc::Cell<CompileTimeEnvironment>>,
) -> usize {
let index = self.code_block.compile_environments.len();
self.code_block.compile_environments.push(environment);
index
Expand Down Expand Up @@ -2551,7 +2554,7 @@ impl<'b> ByteCompiler<'b> {
ConstructorKind::Base
}),
);
code.computed_field_names = Some(gc::GcCell::new(vec![]));
code.computed_field_names = Some(boa_gc::Cell::new(vec![]));
let mut compiler = ByteCompiler {
code_block: code,
literals_map: FxHashMap::default(),
Expand Down
13 changes: 12 additions & 1 deletion boa_engine/src/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl<T: Any + Debug + Trace> NativeObject for T {
}

/// The internal representation of a JavaScript object.
#[derive(Debug, Trace, Finalize)]
#[derive(Debug, Finalize)]
pub struct Object {
/// The type of the object.
pub data: ObjectData,
Expand All @@ -122,6 +122,17 @@ pub struct Object {
private_elements: FxHashMap<Sym, PrivateElement>,
}

unsafe impl Trace for Object {
boa_gc::custom_trace!(this, {
mark(&this.data);
mark(&this.properties);
mark(&this.prototype);
for elem in this.private_elements.values() {
mark(elem);
}
});
}

/// The representation of private object elements.
#[derive(Clone, Debug, Trace, Finalize)]
pub(crate) enum PrivateElement {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::syntax::ast::node::Node;
use boa_gc::{Finalize, Trace};
use boa_interner::{Interner, Sym, ToInternedString};

#[cfg(feature = "deser")]
Expand All @@ -19,7 +18,7 @@ use serde::{Deserialize, Serialize};
/// [spec]: https://tc39.es/ecma262/#prod-ContinueStatement
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Continue {
label: Option<Sym>,
}
Expand Down
2 changes: 2 additions & 0 deletions boa_engine/src/vm/code_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ unsafe impl Readable for f64 {}
#[derive(Clone, Debug, Trace, Finalize)]
pub struct CodeBlock {
/// Name of this function
#[unsafe_ignore_trace]
pub(crate) name: Sym,

/// The number of arguments expected.
Expand All @@ -80,6 +81,7 @@ pub struct CodeBlock {
pub(crate) literals: Vec<JsValue>,

/// Property field names.
#[unsafe_ignore_trace]
pub(crate) names: Vec<Sym>,

/// Locators for all bindings in the codeblock.
Expand Down
2 changes: 1 addition & 1 deletion boa_gc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Garbage collector for the Boa JavaScript engine.

pub use gc::{
custom_trace, force_collect, unsafe_empty_trace, Finalize, Gc, GcCell as Cell,
custom_trace, finalizer_safe, force_collect, unsafe_empty_trace, Finalize, Gc, GcCell as Cell,
GcCellRef as Ref, GcCellRefMut as RefMut, Trace,
};
4 changes: 2 additions & 2 deletions boa_interner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ categories = ["data-structures"]
license = "Unlicense/MIT"

[dependencies]
string-interner = "0.14.0"
serde = { version = "1.0.137", features = ["derive"], optional = true }
gc = { version = "0.4.1", features = ["derive"] }
phf = { version = "0.10.1", features = ["macros"] }
rustc-hash = "1.1.0"
56 changes: 56 additions & 0 deletions boa_interner/src/fixed_string.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use crate::interned_str::InternedStr;

#[derive(Debug, Default)]
pub(super) struct FixedString {
inner: String,
}

impl FixedString {
/// Creates a new, pinned [`FixedString`].
pub(super) fn new(capacity: usize) -> Self {
Self {
inner: String::with_capacity(capacity),
}
}

/// Get the maximum capacity of the [`FixedString`].
pub(super) fn capacity(&self) -> usize {
self.inner.capacity()
}

/// Tries to push `string` to the [`FixedString`], and returns
/// an [`InternedStr`] pointer to the stored `string`, or
/// `None` if the capacity is not enough to store `string`.
///
/// # Safety
///
/// The caller is responsible for ensuring `self` outlives the returned
/// `InternedStr`.
pub(super) unsafe fn push(&mut self, string: &str) -> Option<InternedStr> {
let capacity = self.inner.capacity();
(capacity >= self.inner.len() + string.len()).then(|| {
let old_len = self.inner.len();
self.inner.push_str(string);
// SAFETY: The caller is responsible for extending the lifetime
// of `self` to outlive the return value.
unsafe { InternedStr::new(self.inner[old_len..self.inner.len()].into()) }
})
}

/// Pushes `string` to the [`FixedString`], and returns
/// an [`InternedStr`] pointer to the stored `string`, without
/// checking if the total `capacity` is enough to store `string`.
///
/// # Safety
///
/// The caller is responsible for ensuring that `self` outlives the returned
/// `InternedStr` and that it has enough capacity to store `string` without
/// reallocating.
pub(super) unsafe fn push_unchecked(&mut self, string: &str) -> InternedStr {
let old_len = self.inner.len();
self.inner.push_str(string);
// SAFETY: The caller is responsible for extending the lifetime
// of `self` to outlive the return value.
unsafe { InternedStr::new(self.inner[old_len..self.inner.len()].into()) }
}
}
70 changes: 70 additions & 0 deletions boa_interner/src/interned_str.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use std::{borrow::Borrow, ptr::NonNull};

/// Wrapper for an interned str pointer, required to
/// quickly check using a hash if a string is inside an [`Interner`][`super::Interner`].
///
/// # Safety
///
/// This struct could cause Undefined Behaviour on:
/// - Use without ensuring the referenced memory is still allocated.
/// - Construction of an [`InternedStr`] from an invalid [`NonNull<str>`].
///
/// In general, this should not be used outside of an [`Interner`][`super::Interner`].
#[derive(Debug, Clone)]
pub(super) struct InternedStr {
ptr: NonNull<str>,
}

impl InternedStr {
/// Create a new interned string from the given `str`.
///
/// # Safety
///
/// Not maintaining the invariants specified on the struct definition
/// could cause Undefined Behaviour.
#[inline]
pub(super) unsafe fn new(ptr: NonNull<str>) -> Self {
Self { ptr }
}

/// Returns a shared reference to the underlying string.
///
/// # Safety
///
/// Not maintaining the invariants specified on the struct definition
/// could cause Undefined Behaviour.
#[inline]
pub(super) unsafe fn as_str(&self) -> &str {
// SAFETY: The caller must verify the invariants
// specified on the struct definition.
unsafe { self.ptr.as_ref() }
}
}

impl std::hash::Hash for InternedStr {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
// SAFETY: The caller must verify the invariants
// specified in the struct definition.
unsafe {
self.as_str().hash(state);
}
}
}

impl Eq for InternedStr {}

impl PartialEq for InternedStr {
fn eq(&self, other: &Self) -> bool {
// SAFETY: The caller must verify the invariants
// specified in the struct definition.
unsafe { self.as_str() == other.as_str() }
}
}

impl Borrow<str> for InternedStr {
fn borrow(&self) -> &str {
// SAFETY: The caller must verify the invariants
// specified in the struct definition.
unsafe { self.as_str() }
}
}
Loading

0 comments on commit b1f06a6

Please sign in to comment.