Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Atomics.pause #3956

Merged
merged 1 commit into from
Aug 24, 2024
Merged
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
54 changes: 51 additions & 3 deletions core/engine/src/builtins/atomics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl IntrinsicObject for Atomics {
fn init(realm: &Realm) {
let _timer = Profiler::global().start_event(std::any::type_name::<Self>(), "init");

BuiltInBuilder::with_intrinsic::<Self>(realm)
let builder = BuiltInBuilder::with_intrinsic::<Self>(realm)
.static_property(
JsSymbol::to_string_tag(),
Self::NAME,
Expand All @@ -55,8 +55,12 @@ impl IntrinsicObject for Atomics {
.static_method(Atomics::sub, js_string!("sub"), 3)
.static_method(Atomics::wait, js_string!("wait"), 4)
.static_method(Atomics::notify, js_string!("notify"), 3)
.static_method(Atomics::bit_xor, js_string!("xor"), 3)
.build();
.static_method(Atomics::bit_xor, js_string!("xor"), 3);

#[cfg(feature = "experimental")]
let builder = builder.static_method(Atomics::pause, js_string!("pause"), 0);
jasonwilliams marked this conversation as resolved.
Show resolved Hide resolved

builder.build();
}

fn get(intrinsics: &Intrinsics) -> JsObject {
Expand Down Expand Up @@ -512,6 +516,50 @@ impl Atomics {
// 13. Return 𝔽(n).
Ok(count.into())
}

/// [`Atomics.pause ( [ iterationNumber ] )`][spec]
///
/// [spec]: https://tc39.es/proposal-atomics-microwait/#Atomics.pause
#[cfg(feature = "experimental")]
fn pause(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
use super::Number;

let iteration_number = args.get_or_undefined(0);

// 1. If iterationNumber is not undefined, then
let iterations = if iteration_number.is_undefined() {
1
} else {
// a. If iterationNumber is not an integral Number, throw a TypeError exception.
if !Number::is_integer(iteration_number) {
return Err(JsNativeError::typ()
.with_message("`iterationNumber` must be an integral Number")
.into());
}

// b. If ℝ(iterationNumber) < 0, throw a RangeError exception.
let iteration_number = iteration_number.to_number(context)? as i16;
if iteration_number < 0 {
return Err(JsNativeError::range()
.with_message("`iterationNumber` must be a positive integer")
.into());
}

// Clamp to u16 so that the main thread cannot block using this.
iteration_number as u16
};

// 2. If the execution environment of the ECMAScript implementation supports a signal that the current executing code
// is in a spin-wait loop, send that signal. An ECMAScript implementation may send that signal multiple times,
// determined by iterationNumber when not undefined. The number of times the signal is sent for an integral Number
// N is at most the number of times it is sent for N + 1.
for _ in 0..iterations {
std::hint::spin_loop();
}

// 3. Return undefined.
Ok(JsValue::undefined())
}
}

/// [`ValidateIntegerTypedArray ( typedArray, waitable )`][spec]
Expand Down
4 changes: 0 additions & 4 deletions test262_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,6 @@ features = [
# https://github.com/tc39/proposal-arraybuffer-base64
"uint8array-base64",

# Atomics.pause
# https://github.com/tc39/proposal-atomics-microwait
"Atomics.pause",

### Non-standard
"caller",
]
Expand Down
Loading