Skip to content

Commit

Permalink
Implement Atomics.pause (#3956)
Browse files Browse the repository at this point in the history
  • Loading branch information
jedel1043 authored Aug 24, 2024
1 parent 1691802 commit af4fd5a
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 7 deletions.
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);

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

0 comments on commit af4fd5a

Please sign in to comment.