Skip to content
This repository was archived by the owner on Jul 10, 2023. It is now read-only.

Commit d5f3026

Browse files
author
bors-servo
committed
Auto merge of #45 - nox:appveyor, r=larsbergstrom
Use AppVeyor <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/heapsize/45) <!-- Reviewable:end -->
2 parents 5271fb4 + eec2c5d commit d5f3026

File tree

4 files changed

+106
-22
lines changed

4 files changed

+106
-22
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,8 @@ build = "build.rs"
1010
[build-dependencies]
1111
regex = "0.1"
1212

13+
[dependencies]
14+
kernel32-sys = "0.2.1"
15+
1316
[features]
1417
unstable = []

appveyor.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
environment:
2+
matrix:
3+
- FEATURES: ""
4+
- FEATURES: "unstable"
5+
6+
platform:
7+
- i686-pc-windows-gnu
8+
- i686-pc-windows-msvc
9+
- x86_64-pc-windows-gnu
10+
- x86_64-pc-windows-msvc
11+
12+
install:
13+
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:PLATFORM}.exe"
14+
- rust-nightly-%PLATFORM%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
15+
- SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
16+
- rustc -V
17+
- cargo -V
18+
19+
build_script:
20+
- cargo build --verbose --features "%FEATURES%"
21+
22+
test_script:
23+
- cargo test --verbose --features "%FEATURES%"

src/lib.rs

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
//! Data structure measurement.
66
7+
#[cfg(target_os = "windows")]
8+
extern crate kernel32;
9+
10+
#[cfg(target_os = "windows")]
11+
use kernel32::{GetProcessHeap, HeapSize, HeapValidate};
712
use std::borrow::Cow;
813
use std::cell::{Cell, RefCell};
914
use std::collections::{BTreeMap, HashMap, LinkedList, VecDeque};
@@ -18,39 +23,43 @@ use std::sync::Arc;
1823
use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize};
1924
use std::rc::Rc;
2025

21-
#[cfg(not(target_os = "windows"))]
22-
extern {
23-
#[cfg_attr(any(prefixed_jemalloc, target_os = "macos", target_os = "android"), link_name = "je_malloc_usable_size")]
24-
// Get the size of a heap block.
25-
//
26-
// Ideally Rust would expose a function like this in std::rt::heap, which would avoid the
27-
// jemalloc dependence.
28-
//
29-
// The C prototype is `je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)`. On some
30-
// platforms `JEMALLOC_USABLE_SIZE_CONST` is `const` and on some it is empty. But in practice
31-
// this function doesn't modify the contents of the block that `ptr` points to, so we use
32-
// `*const c_void` here.
33-
fn malloc_usable_size(ptr: *const c_void) -> usize;
34-
}
35-
36-
/// A wrapper for je_malloc_usable_size that handles `EMPTY` and returns `usize`.
26+
/// Get the size of a heap block.
27+
///
28+
/// Ideally Rust would expose a function like this in std::rt::heap.
3729
///
3830
/// `unsafe` because the caller must ensure that the pointer is from jemalloc.
3931
/// FIXME: This probably interacts badly with custom allocators:
4032
/// https://doc.rust-lang.org/book/custom-allocators.html
41-
#[cfg(not(target_os = "windows"))]
4233
pub unsafe fn heap_size_of(ptr: *const c_void) -> usize {
4334
if ptr == 0x01 as *const c_void {
4435
0
4536
} else {
46-
malloc_usable_size(ptr)
37+
heap_size_of_impl(ptr)
4738
}
4839
}
4940

50-
/// FIXME: Need to implement heap size support on Windows.
41+
#[cfg(not(target_os = "windows"))]
42+
unsafe fn heap_size_of_impl(ptr: *const c_void) -> usize {
43+
// The C prototype is `je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)`. On some
44+
// platforms `JEMALLOC_USABLE_SIZE_CONST` is `const` and on some it is empty. But in practice
45+
// this function doesn't modify the contents of the block that `ptr` points to, so we use
46+
// `*const c_void` here.
47+
extern "C" {
48+
#[cfg_attr(any(prefixed_jemalloc, target_os = "macos", target_os = "android"), link_name = "je_malloc_usable_size")]
49+
fn malloc_usable_size(ptr: *const c_void) -> usize;
50+
}
51+
malloc_usable_size(ptr)
52+
}
53+
5154
#[cfg(target_os = "windows")]
52-
pub unsafe fn heap_size_of(ptr: *const c_void) -> usize {
53-
0
55+
pub unsafe fn heap_size_of_impl(mut ptr: *const c_void) -> usize {
56+
let heap = GetProcessHeap();
57+
58+
if HeapValidate(heap, 0, ptr) == 0 {
59+
ptr = *(ptr as *const *const c_void).offset(-1);
60+
}
61+
62+
HeapSize(heap, 0, ptr) as usize
5463
}
5564

5665
// The simplest trait for measuring the size of heap data structures. More complex traits that

tests/tests.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5-
#![cfg_attr(feature= "unstable", feature(alloc, heap_api))]
5+
#![cfg_attr(feature= "unstable", feature(alloc, heap_api, repr_simd))]
66

77
extern crate heapsize;
88

@@ -18,11 +18,15 @@ mod unstable {
1818
use heapsize::heap_size_of;
1919
use std::os::raw::c_void;
2020

21+
#[repr(C, simd)]
22+
struct OverAligned(u64, u64, u64, u64);
23+
2124
#[test]
2225
fn check_empty() {
2326
assert_eq!(::EMPTY, alloc::heap::EMPTY);
2427
}
2528

29+
#[cfg(not(target_os = "windows"))]
2630
#[test]
2731
fn test_alloc() {
2832
unsafe {
@@ -40,8 +44,53 @@ mod unstable {
4044
let x = alloc::heap::allocate(1024 * 1024, 0);
4145
assert_eq!(heap_size_of(x as *const c_void), 1024 * 1024);
4246
alloc::heap::deallocate(x, 1024 * 1024, 0);
47+
48+
// An overaligned 1MiB request is allocated exactly.
49+
let x = alloc::heap::allocate(1024 * 1024, 32);
50+
assert_eq!(heap_size_of(x as *const c_void), 1024 * 1024);
51+
alloc::heap::deallocate(x, 1024 * 1024, 32);
52+
}
53+
}
54+
55+
#[cfg(target_os = "windows")]
56+
#[test]
57+
fn test_alloc() {
58+
unsafe {
59+
// A 64 byte request is allocated exactly.
60+
let x = alloc::heap::allocate(64, 0);
61+
assert_eq!(heap_size_of(x as *const c_void), 64);
62+
alloc::heap::deallocate(x, 64, 0);
63+
64+
// A 255 byte request is allocated exactly.
65+
let x = alloc::heap::allocate(255, 0);
66+
assert_eq!(heap_size_of(x as *const c_void), 255);
67+
alloc::heap::deallocate(x, 255, 0);
68+
69+
// A 1MiB request is allocated exactly.
70+
let x = alloc::heap::allocate(1024 * 1024, 0);
71+
assert_eq!(heap_size_of(x as *const c_void), 1024 * 1024);
72+
alloc::heap::deallocate(x, 1024 * 1024, 0);
73+
74+
// An overaligned 1MiB request is over-allocated.
75+
let x = alloc::heap::allocate(1024 * 1024, 32);
76+
assert_eq!(heap_size_of(x as *const c_void), 1024 * 1024 + 32);
77+
alloc::heap::deallocate(x, 1024 * 1024, 32);
4378
}
4479
}
80+
81+
#[cfg(not(target_os = "windows"))]
82+
#[test]
83+
fn test_simd() {
84+
let x = Box::new(OverAligned(0, 0, 0, 0));
85+
assert_eq!(unsafe { heap_size_of(&*x as *const _ as *const c_void) }, 32);
86+
}
87+
88+
#[cfg(target_os = "windows")]
89+
#[test]
90+
fn test_simd() {
91+
let x = Box::new(OverAligned(0, 0, 0, 0));
92+
assert_eq!(unsafe { heap_size_of(&*x as *const _ as *const c_void) }, 32 + 32);
93+
}
4594
}
4695

4796
#[test]

0 commit comments

Comments
 (0)