Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- main
- releases/**
- dev/oscars-gc

permissions:
contents: read
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ on:
branches:
- main
- releases/**
- dev/oscars-gc
push:
branches:
- main
- releases/**
- dev/oscars-gc
merge_group:
types: [checks_requested]
workflow_dispatch:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/test262.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- main
- releases/**
- dev/oscars-gc

permissions:
contents: read
Expand All @@ -15,6 +16,7 @@ concurrency:

jobs:
run_test262:
if: ${{ github.base_ref != 'dev/oscars-gc' }}
name: Run the test262 test suite
runs-on: ubuntu-latest
timeout-minutes: 60
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/webassembly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ on:
branches:
- main
- releases/**
- dev/oscars-gc
push:
branches:
- main
- releases/**
- dev/oscars-gc
merge_group:
types: [checks_requested]

Expand Down
11 changes: 9 additions & 2 deletions Cargo.lock

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

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ num-integer = "0.1.46"
ryu-js = "1.0.2"
tap = "1.0.1"
thiserror = { version = "2.0.18", default-features = false }
typeid = "1.0.3"
dashmap = "6.2.1"
num_enum = "0.7.6"
itertools = { version = "0.15.0", default-features = false }
Expand Down Expand Up @@ -267,3 +268,6 @@ complexity = { level = "warn", priority = -1 }
perf = { level = "warn", priority = -1 }
pedantic = { level = "warn", priority = -1 }

[patch."https://github.com/boa-dev/boa.git"]
boa_string = { path = "core/string" }

1 change: 1 addition & 0 deletions core/engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ embedded_lz4 = ["boa_macros/embedded_lz4", "lz4_flex"]
jsvalue-enum = []
deser = ["boa_interner/serde", "boa_ast/serde"]
either = ["dep:either", "boa_gc/either"]
oscars_backend = ["boa_gc/oscars_backend", "boa_string/oscars_backend"]

# Enables the `Intl` builtin object and bundles a default ICU4X data provider.
# Prefer this over `intl` if you just want to enable `Intl` without dealing with the
Expand Down
6 changes: 5 additions & 1 deletion core/engine/benches/full.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
fn create_realm(c: &mut Criterion) {
c.bench_function("Create Realm", move |b| {
let root_shape = RootShape::default();
b.iter(|| Realm::create(&DefaultHooks, &root_shape));
b.iter(|| {
Realm::create(&DefaultHooks, &root_shape, &unsafe {
boa_gc::MutationContext::global()
})
});
});
}

Expand Down
16 changes: 9 additions & 7 deletions core/engine/src/builtins/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ impl Eval {
let source_text = SourceText::new(source);
let spanned_source_text = SpannedSourceText::new_source_only(source_text);

let mc = context.gc_collector();
let mut compiler = ByteCompiler::new(
js_string!("<eval>"),
body.strict(),
Expand All @@ -283,6 +284,7 @@ impl Eval {
false,
false,
context.interner_mut(),
&mc,
in_with,
spanned_source_text,
// TODO: Could give more information from previous shadow stack.
Expand Down Expand Up @@ -320,10 +322,8 @@ impl Eval {

compiler.compile_statement_list(body.statements(), true, false);

let code_block = Gc::new(
&unsafe { boa_gc::MutationContext::dummy() },
compiler.finish(),
);
let finished = compiler.finish();
let code_block = context.alloc(finished);

// Strict calls don't need extensions, since all strict eval calls push a new
// function environment before evaluating.
Expand All @@ -350,9 +350,11 @@ impl Eval {
{
let frame = context.vm.frame_mut();
let global = frame.realm.environment();
frame
.environments
.push_lexical(lexical_scope.num_bindings_non_local(), global);
frame.environments.push_lexical(
lexical_scope.num_bindings_non_local(),
&global,
&unsafe { boa_gc::MutationContext::global() },
);
}

context
Expand Down
26 changes: 9 additions & 17 deletions core/engine/src/builtins/finalization_registry/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,7 @@ impl BuiltInConstructor for FinalizationRegistry {
},
);

let weak_registry = WeakGc::new(
&unsafe { boa_gc::MutationContext::dummy() },
registry.inner(),
);
let weak_registry = WeakGc::new(context.gc_collector(), registry.inner());

{
async fn inner_cleanup(
Expand All @@ -174,7 +171,7 @@ impl BuiltInConstructor for FinalizationRegistry {
};

let Some(registry) = weak_registry
.upgrade(&unsafe { boa_gc::MutationContext::dummy() })
.upgrade(&unsafe { boa_gc::MutationContext::global() })
.map(JsObject::from_inner)
else {
return Ok(JsValue::undefined());
Expand Down Expand Up @@ -205,7 +202,7 @@ impl FinalizationRegistry {
/// [`FinalizationRegistry.prototype.register ( target, heldValue [ , unregisterToken ] )`][spec]
///
/// [spec]: https://tc39.es/ecma262/sec-finalization-registry.prototype.register
fn register(this: &JsValue, args: &[JsValue], _context: &mut Context) -> JsResult<JsValue> {
fn register(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
// 1. Let finalizationRegistry be the this value.
// 2. Perform ? RequireInternalSlot(finalizationRegistry, [[Cells]]).
let this = this.as_object();
Expand Down Expand Up @@ -257,10 +254,7 @@ impl FinalizationRegistry {
//
// TODO: support Symbols
let unregister_token = match unregister_token.variant() {
JsVariant::Object(obj) => Some(WeakGc::new(
&unsafe { boa_gc::MutationContext::dummy() },
obj.inner(),
)),
JsVariant::Object(obj) => Some(WeakGc::new(context.gc_collector(), obj.inner())),
// b. Set unregisterToken to empty.
JsVariant::Undefined => None,
// a. If unregisterToken is not undefined, throw a TypeError exception.
Expand All @@ -275,7 +269,7 @@ impl FinalizationRegistry {
// 6. Let cell be the Record { [[WeakRefTarget]]: target, [[HeldValue]]: heldValue, [[UnregisterToken]]: unregisterToken }.
let cell = RegistryCell {
target: Ephemeron::new(
&unsafe { boa_gc::MutationContext::dummy() },
context.gc_collector(),
target_obj.inner(),
CleanupSignaler(Cell::new(Some(
registry.cleanup_notifier.clone().downgrade(),
Expand All @@ -295,7 +289,7 @@ impl FinalizationRegistry {
/// [`FinalizationRegistry.prototype.unregister ( unregisterToken )`][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-finalization-registry.prototype.unregister
fn unregister(this: &JsValue, args: &[JsValue], _context: &mut Context) -> JsResult<JsValue> {
fn unregister(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
// 1. Let finalizationRegistry be the this value.
// 2. Perform ? RequireInternalSlot(finalizationRegistry, [[Cells]]).
let this = this.as_object();
Expand Down Expand Up @@ -338,19 +332,17 @@ impl FinalizationRegistry {

// a. If cell.[[UnregisterToken]] is not empty and SameValue(cell.[[UnregisterToken]], unregisterToken) is true, then
if let Some(tok) = cell.unregister_token.as_ref()
&& let Some(tok) = tok.upgrade(&unsafe { boa_gc::MutationContext::dummy() })
&& let Some(tok) = tok.upgrade(context.gc_collector())
&& Gc::ptr_eq(&tok, unregister_token)
{
// i. Remove cell from finalizationRegistry.[[Cells]].
let cell = registry.cells.swap_remove(i);
let _key = cell
.target
.key(&unsafe { boa_gc::MutationContext::dummy() });
let _key = cell.target.key(context.gc_collector());

// TODO: it might be better to add a special ref for the value that
// also preserves the original key instead.
cell.target
.value(&unsafe { boa_gc::MutationContext::dummy() })
.value(context.gc_collector())
.and_then(|v| v.0.take());

// ii. Set removed to true.
Expand Down
1 change: 1 addition & 0 deletions core/engine/src/builtins/finalization_registry/tests.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[cfg(not(feature = "oscars_backend"))]
mod miri {

use indoc::indoc;
Expand Down
4 changes: 3 additions & 1 deletion core/engine/src/builtins/function/arguments.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![allow(clippy::trivially_copy_pass_by_ref)]
#![allow(clippy::needless_pass_by_value)]
use crate::{
Context, JsData, JsExpect, JsResult, JsValue,
bytecompiler::ToJsString,
Expand Down Expand Up @@ -124,7 +126,7 @@ impl MappedArguments {
.get(index as usize)
.copied()
.flatten()?;
self.environment.get(binding_index)
(*self.environment).get(binding_index)
}

/// Set the value of the binding at the given index in the function environment.
Expand Down
16 changes: 12 additions & 4 deletions core/engine/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,7 @@ impl BuiltInFunctionObject {
let in_with = context.vm.frame().environments.has_object_environment();
let spanned_source_text = SpannedSourceText::new_empty();

let mc = context.gc_collector();
let code = FunctionCompiler::new(spanned_source_text)
.name(js_string!("anonymous"))
.generator(generator)
Expand All @@ -673,6 +674,7 @@ impl BuiltInFunctionObject {
function.scopes(),
function.contains_direct_eval(),
context.interner_mut(),
&mc,
);

let saved = context.vm.frame_mut().environments.pop_to_global();
Expand Down Expand Up @@ -1073,7 +1075,9 @@ pub(crate) fn function_call(
if has_binding_identifier {
let frame = context.vm.frame_mut();
let global = frame.realm.environment();
let index = frame.environments.push_lexical(1, global);
let index = frame
.environments
.push_lexical(1, &global, &unsafe { boa_gc::MutationContext::global() });
Comment on lines 1076 to +1080
frame.environments.put_lexical_value(
BindingLocatorScope::Stack(index),
0,
Expand All @@ -1090,7 +1094,8 @@ pub(crate) fn function_call(
frame.environments.push_function(
scope,
FunctionSlots::new(this, function_object.clone(), None),
global,
&global,
&unsafe { boa_gc::MutationContext::global() },
);
}

Expand Down Expand Up @@ -1181,7 +1186,9 @@ fn function_construct(
if has_binding_identifier {
let frame = context.vm.frame_mut();
let global = frame.realm.environment();
let index = frame.environments.push_lexical(1, global);
let index = frame
.environments
.push_lexical(1, &global, &unsafe { boa_gc::MutationContext::global() });
frame.environments.put_lexical_value(
BindingLocatorScope::Stack(index),
0,
Expand Down Expand Up @@ -1209,7 +1216,8 @@ fn function_construct(
.clone(),
),
),
global,
&global,
&unsafe { boa_gc::MutationContext::global() },
);
}

Expand Down
2 changes: 1 addition & 1 deletion core/engine/src/builtins/generator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub(crate) enum GeneratorState {
// Need to manually implement, since `Trace` adds a `Drop` impl which disallows destructuring.
unsafe impl Trace for GeneratorState {
custom_trace!(this, mark, {
match &this {
match this {
Self::SuspendedStart { context } | Self::SuspendedYield { context } => mark(context),
Self::Executing | Self::Completed => {}
}
Expand Down
2 changes: 1 addition & 1 deletion core/engine/src/builtins/intl/list_format/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ impl ListFormat {
part: writeable::Part,
mut f: impl FnMut(&mut Self::SubPartsWrite) -> core::fmt::Result,
) -> core::fmt::Result {
assert!(part.category == "list");
assert_eq!(part.category, "list");
let mut string = WriteString(String::new());
f(&mut string)?;
if !string.0.is_empty() {
Expand Down
13 changes: 9 additions & 4 deletions core/engine/src/builtins/intl/locale/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,14 +349,17 @@ impl Locale {
// 1. Let loc be the this value.
// 2. Perform ? RequireInternalSlot(loc, [[InitializedLocale]]).
let object = this.as_object();
// Under `oscars_backend`, `downcast_ref` returns `GcRef<'_, Locale>`.
// Deref through the guard before cloning to get an owned `icu_locale::Locale`.
// This is required because `GcRef<'_, Locale>` doesn't implement `NativeObject`.
let mut loc = object
.as_ref()
.and_then(|o| o.downcast_ref::<icu_locale::Locale>())
.ok_or_else(|| {
JsNativeError::typ()
.with_message("`Locale.maximize` can only be called on a `Locale` object")
})?
.clone();
})
.map(|r| (*r).clone())?;

// 3. Let maximal be the result of the Add Likely Subtags algorithm applied to loc.[[Locale]]. If an error is signaled, set maximal to loc.[[Locale]].
context
Expand Down Expand Up @@ -387,15 +390,17 @@ impl Locale {
// 1. Let loc be the this value.
// 2. Perform ? RequireInternalSlot(loc, [[InitializedLocale]]).
let object = this.as_object();
// Under `oscars_backend`, `downcast_ref` returns `GcRef<'_, Locale>`.
// Deref through the guard before cloning to get an owned `icu_locale::Locale`.
let mut loc = object
.as_ref()
.and_then(|o| o.downcast_ref::<icu_locale::Locale>())
.ok_or_else(|| {
JsNativeError::typ().with_message(
"`Locale.prototype.minimize` can only be called on a `Locale` object",
)
})?
.clone();
})
.map(|r| (*r).clone())?;

// 3. Let minimal be the result of the Remove Likely Subtags algorithm applied to loc.[[Locale]]. If an error is signaled, set minimal to loc.[[Locale]].
context
Expand Down
Loading
Loading