@@ -345,47 +345,94 @@ mod imp {
345345 not( jemalloc) ,
346346 windows) ) ]
347347mod imp {
348- use libc:: { c_void, size_t} ;
349- use libc;
348+ use core:: mem:: size_of;
349+ use libc:: { BOOL , DWORD , HANDLE , LPVOID , SIZE_T , INVALID_HANDLE_VALUE } ;
350+ use libc:: { WriteFile } ;
350351 use super :: MIN_ALIGN ;
351352
352- extern {
353- fn _aligned_malloc ( size : size_t , align : size_t ) -> * mut c_void ;
354- fn _aligned_realloc ( block : * mut c_void , size : size_t ,
355- align : size_t ) -> * mut c_void ;
356- fn _aligned_free ( ptr : * mut c_void ) ;
353+ extern "system" {
354+ fn GetProcessHeap ( ) -> HANDLE ;
355+ fn GetStdHandle ( nStdHandle : DWORD ) -> HANDLE ;
356+ fn HeapAlloc ( hHeap : HANDLE , dwFlags : DWORD , dwBytes : SIZE_T ) -> LPVOID ;
357+ fn HeapReAlloc ( hHeap : HANDLE , dwFlags : DWORD , lpMem : LPVOID , dwBytes : SIZE_T ) -> LPVOID ;
358+ fn HeapFree ( hHeap : HANDLE , dwFlags : DWORD , lpMem : LPVOID ) -> BOOL ;
359+ fn HeapSummary ( hHeap : HANDLE , dwFlags : DWORD , lpSummary : LPHEAP_SUMMARY ) -> BOOL ;
360+ }
361+
362+ #[ repr( C ) ] #[ allow( non_snake_case) ]
363+ struct HEAP_SUMMARY {
364+ cb : DWORD ,
365+ cbAllocated : SIZE_T ,
366+ cbCommitted : SIZE_T ,
367+ cbReserved : SIZE_T ,
368+ cbMaxReserve : SIZE_T ,
369+ }
370+ #[ allow( non_camel_case_types) ]
371+ type LPHEAP_SUMMARY = * mut HEAP_SUMMARY ;
372+
373+ #[ repr( C ) ]
374+ struct Header ( * mut u8 ) ;
375+
376+ const HEAP_REALLOC_IN_PLACE_ONLY : DWORD = 0x00000010 ;
377+ const STD_OUTPUT_HANDLE : DWORD = -11i32 as u32 ;
378+
379+ #[ inline]
380+ unsafe fn get_header < ' a > ( ptr : * mut u8 ) -> & ' a mut Header {
381+ & mut * ( ptr as * mut Header ) . offset ( -1 )
382+ }
383+
384+ #[ inline]
385+ unsafe fn align_ptr ( ptr : * mut u8 , align : usize ) -> * mut u8 {
386+ let aligned = ptr. offset ( ( align - ( ptr as usize & ( align - 1 ) ) ) as isize ) ;
387+ * get_header ( aligned) = Header ( ptr) ;
388+ aligned
357389 }
358390
359391 #[ inline]
360392 pub unsafe fn allocate ( size : usize , align : usize ) -> * mut u8 {
361393 if align <= MIN_ALIGN {
362- libc :: malloc ( size as size_t ) as * mut u8
394+ HeapAlloc ( GetProcessHeap ( ) , 0 , size as SIZE_T ) as * mut u8
363395 } else {
364- _aligned_malloc ( size as size_t , align as size_t ) as * mut u8
396+ let ptr = HeapAlloc ( GetProcessHeap ( ) , 0 , ( size + align) as SIZE_T ) as * mut u8 ;
397+ if ptr. is_null ( ) { return ptr }
398+ align_ptr ( ptr, align)
365399 }
366400 }
367401
368402 #[ inline]
369403 pub unsafe fn reallocate ( ptr : * mut u8 , _old_size : usize , size : usize , align : usize ) -> * mut u8 {
370404 if align <= MIN_ALIGN {
371- libc :: realloc ( ptr as * mut c_void , size as size_t ) as * mut u8
405+ HeapReAlloc ( GetProcessHeap ( ) , 0 , ptr as LPVOID , size as SIZE_T ) as * mut u8
372406 } else {
373- _aligned_realloc ( ptr as * mut c_void , size as size_t , align as size_t ) as * mut u8
407+ let header = get_header ( ptr) ;
408+ let new = HeapReAlloc ( GetProcessHeap ( ) , 0 , header. 0 as LPVOID ,
409+ ( size + align) as SIZE_T ) as * mut u8 ;
410+ if new. is_null ( ) { return new }
411+ align_ptr ( new, align)
374412 }
375413 }
376414
377415 #[ inline]
378- pub unsafe fn reallocate_inplace ( _ptr : * mut u8 , old_size : usize , _size : usize ,
379- _align : usize ) -> usize {
380- old_size
416+ pub unsafe fn reallocate_inplace ( ptr : * mut u8 , old_size : usize , size : usize ,
417+ align : usize ) -> usize {
418+ if align <= MIN_ALIGN {
419+ let new = HeapReAlloc ( GetProcessHeap ( ) , HEAP_REALLOC_IN_PLACE_ONLY , ptr as LPVOID ,
420+ size as SIZE_T ) as * mut u8 ;
421+ if new. is_null ( ) { old_size } else { size }
422+ } else {
423+ old_size
424+ }
381425 }
382426
383427 #[ inline]
384428 pub unsafe fn deallocate ( ptr : * mut u8 , _old_size : usize , align : usize ) {
385429 if align <= MIN_ALIGN {
386- libc:: free ( ptr as * mut libc:: c_void )
430+ let err = HeapFree ( GetProcessHeap ( ) , 0 , ptr as LPVOID ) ;
431+ debug_assert ! ( err != 0 ) ;
387432 } else {
388- _aligned_free ( ptr as * mut c_void )
433+ let header = get_header ( ptr) ;
434+ let err = HeapFree ( GetProcessHeap ( ) , 0 , header. 0 as LPVOID ) ;
435+ debug_assert ! ( err != 0 ) ;
389436 }
390437 }
391438
@@ -394,7 +441,45 @@ mod imp {
394441 size
395442 }
396443
397- pub fn stats_print ( ) { }
444+ pub fn stats_print ( ) {
445+ use core:: fmt:: { Error , Result , Write } ;
446+ use core:: ptr:: null_mut;
447+ use core:: raw:: Repr ;
448+ use core:: result:: Result :: { Ok , Err } ;
449+ struct Console ( HANDLE ) ;
450+ impl Write for Console {
451+ fn write_str ( & mut self , s : & str ) -> Result {
452+ let repr = s. repr ( ) ;
453+ let mut written = 0 ;
454+ let err = unsafe { WriteFile ( self . 0 , repr. data as LPVOID , repr. len as DWORD ,
455+ & mut written, null_mut ( ) ) } ;
456+ if written as usize != repr. len { return Err ( Error ) }
457+ if err == 0 { return Err ( Error ) }
458+ Ok ( ( ) )
459+ }
460+ }
461+ let mut hs = HEAP_SUMMARY {
462+ cb : size_of :: < HEAP_SUMMARY > ( ) as DWORD ,
463+ cbAllocated : 0 ,
464+ cbCommitted : 0 ,
465+ cbReserved : 0 ,
466+ cbMaxReserve : 0 ,
467+ } ;
468+ let err = unsafe { HeapSummary ( GetProcessHeap ( ) , 0 , & mut hs) } ;
469+ assert ! ( err != 0 ) ;
470+ let handle = unsafe { GetStdHandle ( STD_OUTPUT_HANDLE ) } ;
471+ if handle. is_null ( ) || handle == INVALID_HANDLE_VALUE { panic ! ( "Failed to open stdout" ) }
472+ let mut out = Console ( handle) ;
473+ writeln ! ( & mut out, "Allocated: {}" , hs. cbAllocated) . unwrap ( ) ;
474+ writeln ! ( & mut out, "Committed: {}" , hs. cbCommitted) . unwrap ( ) ;
475+ writeln ! ( & mut out, "Reserved: {}" , hs. cbReserved) . unwrap ( ) ;
476+ writeln ! ( & mut out, "MaxReserve: {}" , hs. cbMaxReserve) . unwrap ( ) ;
477+ }
478+
479+ #[ test]
480+ fn alignment_header_size ( ) {
481+ assert ! ( size_of:: <Header >( ) <= MIN_ALIGN ) ;
482+ }
398483}
399484
400485#[ cfg( test) ]
0 commit comments