Skip to content

Commit

Permalink
Check upstream for changes in CI
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda committed Dec 8, 2024
1 parent 1bae70d commit 95c0f72
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 49 deletions.
18 changes: 18 additions & 0 deletions .github/upstream-sources.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
{ "owner": "rust-lang", "repo": "libm", "tag": "libm-v0.2.11", "path": "src/math/trunc.rs" },
{ "owner": "rust-lang", "repo": "libm", "tag": "libm-v0.2.11", "path": "src/math/copysign.rs" },
{ "owner": "rust-lang", "repo": "libm", "tag": "libm-v0.2.11", "path": "src/math/round.rs" },
{ "owner": "rust-lang", "repo": "rust", "tag": "1.83.0", "path": "library/core/src/time.rs" },
{
"owner": "rust-lang",
"repo": "rust",
"tag": "1.82.0",
"path": "library/std/src/sys/alloc/wasm.rs"
},
{
"owner": "serde-rs",
"repo": "serde",
"tag": "v1.0.215",
"path": "serde/src/de/impls.rs"
}
]
57 changes: 57 additions & 0 deletions .github/workflows/upstream.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Upstream check

on:
push:
branches: ["main"]
pull_request:
schedule:
- cron: "0 7 * * *"

concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}
cancel-in-progress: true

jobs:
check:
name: Check upstream for changes

runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4
- name: Test
uses: actions/github-script@v7
with:
script: |
const upstreamSources = require('./.github/upstream-sources.json')
for (const source of upstreamSources) {
Promise.all([
github.rest.repos.getContent({
owner: source.owner,
repo: source.repo,
path: source.path,
ref: source.tag,
}),
github.rest.repos
.getLatestRelease({
owner: source.owner,
repo: source.repo,
})
.then((tags) => {
return github.rest.repos.getContent({
owner: source.owner,
repo: source.repo,
path: source.path,
ref: tags.data.tag_name,
})
}),
]).then(([current, latest]) => {
if (current.data.sha != latest.data.sha) {
core.setFailed(`
<${current.data.html_url}> has been updated to <${latest.data.html_url}>.
Check if the relevant code needs to be updated and then update the entry in \`.github/upstream-sources.json\`.
`)
}
})
}
46 changes: 30 additions & 16 deletions benches/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,26 @@ pub fn main() {
Duration::from_secs_f64(time_stamp) / 1000
});
benchmark("`Duration::from_secs_f64()` with rounding", |time_stamp| {
// See <https://doc.rust-lang.org/1.73.0/src/core/time.rs.html#657-668>.
// Inspired by <https://github.com/rust-lang/rust/blob/1.83.0/library/core/src/time.rs#L822-L833>.
/// Number of nanoseconds in a second.
const NANOS_PER_SEC: u64 = 1_000_000_000;
let rhs: u32 = 1000;
let time_stamp = Duration::from_secs_f64(time_stamp);
let secs = time_stamp.as_secs() / 1000;
let carry = time_stamp.as_secs() - secs * 1000;
let extra_nanos = (carry * 1_000_000_000 / 1000) as u32;
let nanos = time_stamp.subsec_micros()
+ u32::from(time_stamp.subsec_nanos() % 1000 > 499)
+ extra_nanos;
let (secs, extra_secs) = (
time_stamp.as_secs() / u64::from(rhs),
time_stamp.as_secs() % u64::from(rhs),
);
let (mut nanos, extra_nanos) = (
time_stamp.subsec_nanos() / rhs,
time_stamp.subsec_nanos() % rhs,
);
// CHANGED: Extracted part of the calculation into variable.
let extra = extra_secs * NANOS_PER_SEC + u64::from(extra_nanos);
nanos += u32::try_from(extra / u64::from(rhs)).unwrap();
// CHANGED: Added rounding.
nanos += u32::from(extra % u64::from(rhs) >= u64::from(rhs / 2));
// CHANGED: Removed check that would fail because of the additional time added
// by rounding.
Duration::new(secs, nanos)
});
}
Expand Down Expand Up @@ -186,19 +198,17 @@ impl F64 {
}

/// Adjusted [`Duration::from_secs_f64()`].
///
/// See <https://doc.rust-lang.org/1.73.0/src/core/time.rs.html#1262-1340>.
#[expect(warnings, reason = "code is copied")]
fn adjusted_std(time_stamp: f64) -> Duration {
// CHANGED: 1G to 1M.
const NANOS_PER_MILLI: u32 = 1_000_000;

// See <https://doc.rust-lang.org/1.73.0/src/core/time.rs.html#1477-1484>.
// See <https://github.com/rust-lang/rust/blob/1.83.0/library/core/src/time.rs#L1694-L1703>.
const MANT_BITS: i16 = 52;
const EXP_BITS: i16 = 11;
const OFFSET: i16 = 44;

// See <https://doc.rust-lang.org/1.73.0/src/core/time.rs.html#1262-1340>.
// See <https://github.com/rust-lang/rust/blob/1.83.0/library/core/src/time.rs#L1480-L1558>.
const MIN_EXP: i16 = 1 - (1_i16 << EXP_BITS) / 2;
const MANT_MASK: u64 = (1 << MANT_BITS) - 1;
const EXP_MASK: u64 = (1 << 1_i16 << EXP_BITS) - 1;
Expand Down Expand Up @@ -277,13 +287,17 @@ fn adjusted_std(time_stamp: f64) -> Duration {
panic!("can not convert float seconds to Duration: value is either too big or NaN")
};

let secs = millis / 1000;
let carry = millis - secs * 1000;
let extra_nanos = carry * u64::from(NANOS_PER_MILLI);
nanos += extra_nanos as u32;
// Inspired by <https://github.com/rust-lang/rust/blob/1.83.0/library/core/src/time.rs#L822-L833>.
/// Number of nanoseconds in a second.
const NANOS_PER_SEC: u64 = 1_000_000_000;
let rhs: u32 = 1000;

let (secs, extra_secs) = (millis / u64::from(rhs), millis % u64::from(rhs));
// CHANGED: Nanos were already calculated during the conversion.
nanos += u32::try_from((extra_secs * NANOS_PER_SEC) / u64::from(rhs)).unwrap();

debug_assert!(
nanos < 1_000_000_000,
u64::from(nanos) < NANOS_PER_SEC,
"impossible amount of nanoseconds found"
);

Expand Down
28 changes: 18 additions & 10 deletions src/time/instant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,19 +282,27 @@ mod test {
struct ControlDuration(Duration);

impl ControlDuration {
/// Implements conversion from `DOMHighResTimeStamp` to [`Duration`] by
/// using [`Duration::checked_div()`].
/// Implements perfect but expensive conversion from
/// `DOMHighResTimeStamp` to [`Duration`].
fn new(time_stamp: f64) -> Self {
// See <https://doc.rust-lang.org/1.73.0/src/core/time.rs.html#657-668>.
// Inspired by <https://github.com/rust-lang/rust/blob/1.83.0/library/core/src/time.rs#L822-L833>.
/// Number of nanoseconds in a second.
const NANOS_PER_SEC: u64 = 1_000_000_000;
let rhs: u32 = 1000;
let time_stamp = Duration::from_secs_f64(time_stamp);
let secs = time_stamp.as_secs() / 1000;
let carry = time_stamp.as_secs() - secs * 1000;
#[allow(clippy::as_conversions, clippy::cast_possible_truncation)]
let extra_nanos = (carry * 1_000_000_000 / 1000) as u32;
let (secs, extra_secs) = (
time_stamp.as_secs() / u64::from(rhs),
time_stamp.as_secs() % u64::from(rhs),
);
let (mut nanos, extra_nanos) = (
time_stamp.subsec_nanos() / rhs,
time_stamp.subsec_nanos() % rhs,
);
// CHANGED: Extracted part of the calculation into variable.
let extra = extra_secs * NANOS_PER_SEC + u64::from(extra_nanos);
nanos += u32::try_from(extra / u64::from(rhs)).unwrap();
// CHANGED: Added rounding.
let nanos = time_stamp.subsec_micros()
+ u32::from(time_stamp.subsec_nanos() % 1000 > 499)
+ extra_nanos;
nanos += u32::from(extra % u64::from(rhs) >= u64::from(rhs / 2));
// CHANGED: Removed check that would fail because of the additional time added
// by rounding.
Self(Duration::new(secs, nanos))
Expand Down
4 changes: 2 additions & 2 deletions src/time/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
//! compatible with Serde's implementation for [`std::time::SystemTime`].
//!
//! This implementation was copied from Serde's
//! [`Deserialize`](https://github.com/serde-rs/serde/blob/5fa711d75d91173aafc6019e03cf8af6ac9ba7b2/serde/src/de/impls.rs#L2168-L2314),
//! [`Deserialize`](https://github.com/serde-rs/serde/blob/v1.0.215/serde/src/de/impls.rs#L2282-L2426),
//! and
//! [`Serialize`](https://github.com/serde-rs/serde/blob/5fa711d75d91173aafc6019e03cf8af6ac9ba7b2/serde/src/ser/impls.rs#L730-L747)
//! [`Serialize`](https://github.com/serde-rs/serde/blob/v1.0.215/serde/src/ser/impls.rs#L753-L768)
//! implementation.
#![allow(warnings)]
Expand Down
56 changes: 35 additions & 21 deletions tests-web/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,11 @@ mod allocator {
//! See <https://github.com/rust-lang/rust/blob/1.82.0/library/std/src/sys/alloc/wasm.rs>.
use core::alloc::{GlobalAlloc, Layout};
use core::sync::atomic::{AtomicBool, Ordering};

use dlmalloc::Dlmalloc;

/// The allocator.
static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::Dlmalloc::new();
/// The lock flag.
static LOCKED: AtomicBool = AtomicBool::new(false);
static mut DLMALLOC: Dlmalloc = Dlmalloc::new();
/// Global allocator.
#[global_allocator]
static ALLOC: System = System;
Expand All @@ -37,7 +36,7 @@ mod allocator {
unsafe impl GlobalAlloc for System {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let _lock = lock();
let _lock = lock::lock();
// SAFETY: `DLMALLOC` access is guaranteed to be safe because the lock gives us
// unique and non-reentrant access. Calling `malloc()` is safe because
// preconditions on this function match the trait method preconditions.
Expand All @@ -46,7 +45,7 @@ mod allocator {

#[inline]
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
let _lock = lock();
let _lock = lock::lock();
// SAFETY: `DLMALLOC` access is guaranteed to be safe because the lock gives us
// unique and non-reentrant access. Calling `calloc()` is safe because
// preconditions on this function match the trait method preconditions.
Expand All @@ -55,7 +54,7 @@ mod allocator {

#[inline]
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
let _lock = lock();
let _lock = lock::lock();
// SAFETY: `DLMALLOC` access is guaranteed to be safe because the lock gives us
// unique and non-reentrant access. Calling `free()` is safe because
// preconditions on this function match the trait method preconditions.
Expand All @@ -64,7 +63,7 @@ mod allocator {

#[inline]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
let _lock = lock();
let _lock = lock::lock();
// SAFETY: `DLMALLOC` access is guaranteed to be safe because the lock gives us
// unique and non-reentrant access. Calling `realloc()` is safe because
// preconditions on this function match the trait method preconditions.
Expand All @@ -79,22 +78,37 @@ mod allocator {
}
}

/// The lock guard.
struct DropLock;
/// Lock implementation.
#[cfg(target_feature = "atomics")]
mod lock {
use core::sync::atomic::{AtomicBool, Ordering};

/// Create a [`DropLock`].
fn lock() -> DropLock {
while LOCKED
.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
.is_err()
{}
/// The lock flag.
// CHANGED: using an `AtomicBool` instead of an `AtomicU32`.
static LOCKED: AtomicBool = AtomicBool::new(false);

DropLock
}
/// The lock guard.
pub(super) struct DropLock;

/// Create a [`DropLock`].
pub(super) fn lock() -> DropLock {
loop {
if !LOCKED.swap(true, Ordering::Acquire) {
return DropLock;
}
}
}

impl Drop for DropLock {
fn drop(&mut self) {
LOCKED.swap(false, Ordering::Release);
impl Drop for DropLock {
fn drop(&mut self) {
LOCKED.swap(false, Ordering::Release);
}
}
}

/// Empty lock implementation when threads are not available.
#[cfg(not(target_feature = "atomics"))]
mod lock {
pub(super) fn lock() {}
}
}

0 comments on commit 95c0f72

Please sign in to comment.