зеркало из https://github.com/mozilla/gecko-dev.git
Removing old cfm build files. Use the CFM_LAST_RITES tag to resurrect. r=macdev
This commit is contained in:
Родитель
b636b51c8e
Коммит
d36d169b61
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,44 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
//
|
||||
// Specific defines for the Memory allocator
|
||||
//
|
||||
|
||||
|
||||
#include "MemAllocatorConfig.h"
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
###
|
||||
### This file was generated by AnnotateExports (Friday, March 6, 1998 5:46:22 PM) from MemAllocator.exp.
|
||||
###
|
||||
### [Un-]Comment-out (do not delete) symbols and annotate with #{code} and #{data} to control export.
|
||||
### When brand new signatures are to be exported, regenerate this file as described in AnnotateExports.
|
||||
### Warning: all comments MUST start in the left column, or else stubs will be built wrong.
|
||||
###
|
||||
|
||||
|
||||
###
|
||||
### Symbols you may have to hand annotate with #{code} or #{data}...
|
||||
###
|
||||
|
||||
calloc
|
||||
free
|
||||
malloc
|
||||
realloc
|
||||
|
||||
###
|
||||
### Symbols which do not require hand annotation...
|
||||
###
|
||||
|
||||
#{code}
|
||||
__dl__FPv
|
||||
__nw__FUl
|
||||
__dla__FPv
|
||||
__nwa__FUl
|
||||
__nwa__FUlRCQ23std9nothrow_t
|
||||
__nw__FUlRCQ23std9nothrow_t
|
||||
|
||||
GC_stderr
|
||||
GC_stdout
|
||||
GC_trace_object
|
||||
MWUnmangle
|
||||
GC_malloc_atomic
|
||||
GC_address_to_source
|
||||
GC_gcollect
|
||||
GC_generic_init_threads
|
||||
GC_clear_roots
|
||||
GC_unregister_fragment
|
||||
GC_register_fragment
|
|
@ -1,7 +0,0 @@
|
|||
# Build MemAllocatorStubsPPCLib
|
||||
|
||||
Evaluate % = ("{{SourceFile}}" =~ /(Å:)¨0Å/)
|
||||
|
||||
MakeStub "{{SourceFile}}" -o "{{¨0}}MemAllocatorStubsPPCLib" ¶
|
||||
-fragname MemoryAllocator ¶
|
||||
-vercur 400 -verdef 400 -verimp 400
|
|
@ -1,7 +0,0 @@
|
|||
# Build MemAllocatorStubsPPCLib
|
||||
|
||||
Evaluate % = ("{{SourceFile}}" =~ /(Å:)¨0Å/)
|
||||
|
||||
MakeStub "{{SourceFile}}" -o "{{¨0}}:::dist:client_stubs:MemAllocatorStubsLib" ¶
|
||||
-fragname MemoryAllocator ¶
|
||||
-vercur 400 -verdef 400 -verimp 400
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,71 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* must be first in order to correctly pick up TARGET_CARBON define before
|
||||
* it is set in ConditionalMacros.h */
|
||||
#include "DefinesMac.h"
|
||||
|
||||
#include <Types.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "IDE_Options.h"
|
||||
|
||||
#pragma exceptions off
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
/* Debug macros and switches */
|
||||
|
||||
#define DEBUG_HEAP_INTEGRITY 1
|
||||
#define STATS_MAC_MEMORY 0
|
||||
|
||||
#define MEM_ASSERT(condition, message) ((condition) ? ((void)0) : DebugStr("\p"message))
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/* Non-debug macros and switches */
|
||||
#define DEBUG_HEAP_INTEGRITY 0
|
||||
#define STATS_MAC_MEMORY 0
|
||||
|
||||
|
||||
|
||||
#define MEM_ASSERT(condition, message) ((void)0)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
//
|
||||
// Debug specific defines for the Memory allocators
|
||||
//
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
#include "MemAllocatorConfig.h"
|
|
@ -1,18 +0,0 @@
|
|||
InitializeMemoryTracker
|
||||
ExitMemoryTracker
|
||||
DumpMemoryTrackerState
|
||||
DumpAllocationSites
|
||||
NewAllocationSite
|
||||
TrackItem
|
||||
ReleaseItem
|
||||
NewAllocationSet
|
||||
DisposeAllocationSet
|
||||
LogAllocationSetState
|
||||
EnableAllocationSet
|
||||
DisableAllocationSet
|
||||
DisableMemoryTracker
|
||||
EnableMemoryTracker
|
||||
GetCurrentNativeStackTrace
|
||||
GetCurrentStackPointer
|
||||
GetCurrentStackTrace
|
||||
SetTrackerDataDecoder
|
|
@ -1,48 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
NSPR_BEGIN_EXTERN_C
|
||||
|
||||
void* Flush_Allocate(size_t, Boolean);
|
||||
void Flush_Free(void *);
|
||||
void* Flush_Reallocate(void *, size_t);
|
||||
|
||||
NSPR_END_EXTERN_C
|
|
@ -1,89 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __MACMEMALLOCATOR__
|
||||
#define __MACMEMALLOCATOR__
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <Types.h>
|
||||
|
||||
#warning "This file should not be used"
|
||||
|
||||
typedef struct FreeMemoryStats FreeMemoryStats;
|
||||
|
||||
struct FreeMemoryStats {
|
||||
uint32 totalHeapSize;
|
||||
uint32 totalFreeBytes;
|
||||
uint32 maxBlockSize;
|
||||
};
|
||||
|
||||
typedef void (*MallocHeapLowWarnProc)(void);
|
||||
|
||||
NSPR_BEGIN_EXTERN_C
|
||||
|
||||
typedef unsigned char (*MemoryCacheFlusherProc)(size_t size);
|
||||
typedef void (*PreAllocationHookProc)(void);
|
||||
|
||||
extern void InstallPreAllocationHook(PreAllocationHookProc newHook);
|
||||
extern void InstallMemoryCacheFlusher(MemoryCacheFlusherProc newFlusher);
|
||||
|
||||
// Entry into the memory system's cache flushing
|
||||
extern UInt8 CallCacheFlushers(size_t blockSize);
|
||||
|
||||
extern void* reallocSmaller(void* block, size_t newSize);
|
||||
|
||||
void memtotal ( size_t blockSize, FreeMemoryStats * stats );
|
||||
|
||||
size_t memsize ( void * block );
|
||||
|
||||
extern Boolean gMemoryInitialized;
|
||||
|
||||
void MacintoshInitializeMemory(void);
|
||||
void CallFE_LowMemory(void);
|
||||
Boolean Memory_ReserveInMacHeap(size_t spaceNeeded);
|
||||
Boolean Memory_ReserveInMallocHeap(size_t spaceNeeded);
|
||||
Boolean InMemory_ReserveInMacHeap();
|
||||
size_t Memory_FreeMemoryRemaining();
|
||||
void InstallGarbageCollectorCacheFlusher(const MemoryCacheFlusherProc inFlusher);
|
||||
void InstallMallocHeapLowProc( MallocHeapLowWarnProc proc );
|
||||
|
||||
NSPR_END_EXTERN_C
|
||||
|
||||
#endif
|
|
@ -1,75 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#if DEBUG_MAC_MEMORY
|
||||
#include "xp_tracker.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some mac specific routines and constants
|
||||
*/
|
||||
|
||||
#define kNameMaxLength 30
|
||||
|
||||
|
||||
/* allocType */
|
||||
typedef enum {
|
||||
kMallocBlock = 'mllc',
|
||||
kHandleBlock = 'hndl',
|
||||
kPointerBlock = 'pntr'
|
||||
} AllocatorType;
|
||||
|
||||
/*
|
||||
* Stack Crawl Cheese
|
||||
*/
|
||||
|
||||
void *GetCurrentStackPointer();
|
||||
|
||||
/* walk past any 68K stack frames and try to get a native only trace */
|
||||
void GetCurrentNativeStackTrace(void **stackCrawl);
|
||||
|
||||
/* get a stack crawl from the current stack frame */
|
||||
void GetCurrentStackTrace(void **stackCrawl);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,83 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <new>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
|
||||
// needed because we are not compiling the relevant parts of New.cp
|
||||
std::nothrow_t nothrow;
|
||||
|
||||
void* operator new (size_t size, const std::nothrow_t& ) throw()
|
||||
{
|
||||
return malloc( size );
|
||||
}
|
||||
|
||||
|
||||
void* operator new( size_t size )
|
||||
{
|
||||
return operator new ( size, ::nothrow );
|
||||
}
|
||||
|
||||
void operator delete( void* block )
|
||||
{
|
||||
free( block );
|
||||
}
|
||||
|
||||
|
||||
void* operator new[]( size_t size )
|
||||
{
|
||||
return operator new(size);
|
||||
}
|
||||
|
||||
void* operator new[] (size_t size, const std::nothrow_t& nt ) throw()
|
||||
{
|
||||
return operator new(size, nt);
|
||||
}
|
||||
|
||||
void operator delete[]( void* block )
|
||||
{
|
||||
operator delete(block);
|
||||
}
|
||||
|
|
@ -1,812 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#pragma error "This file is obsolete, but remains for reference reasons"
|
||||
|
||||
#include <Memory.h>
|
||||
#include <Processes.h>
|
||||
|
||||
#include "stdlib.h"
|
||||
|
||||
#include "TypesAndSwitches.h"
|
||||
#include "MacMemAllocator.h"
|
||||
|
||||
#include "prlog.h"
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
#include "prglobal.h"
|
||||
#include "prfile.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
#if DEBUG_MAC_MEMORY
|
||||
#include "MemoryTracker.h"
|
||||
|
||||
|
||||
extern AllocationSet * gFixedSizeAllocatorSet;
|
||||
extern AllocationSet * gSmallHeapAllocatorSet;
|
||||
extern AllocationSet * gLargeBlockAllocatorSet;
|
||||
#endif
|
||||
|
||||
void * gOurApplicationHeapBase;
|
||||
void * gOurApplicationHeapMax;
|
||||
|
||||
Boolean gMemoryInitialized = false;
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark DECLARATIONS AND ENUMERATIONS
|
||||
|
||||
typedef struct MemoryCacheFlusherProcRec MemoryCacheFlusherProcRec;
|
||||
|
||||
struct MemoryCacheFlusherProcRec {
|
||||
MemoryCacheFlusherProc flushProc;
|
||||
MemoryCacheFlusherProcRec *next;
|
||||
};
|
||||
|
||||
typedef struct PreAllocationProcRec PreAllocationProcRec;
|
||||
|
||||
struct PreAllocationProcRec {
|
||||
PreAllocationHookProc preAllocProc;
|
||||
PreAllocationProcRec *next;
|
||||
};
|
||||
|
||||
MemoryCacheFlusherProcRec *gFirstFlusher = NULL;
|
||||
PreAllocationProcRec *gFirstPreAllocator = NULL;
|
||||
MallocHeapLowWarnProc gMallocLowProc = NULL;
|
||||
|
||||
void CallPreAllocators(void);
|
||||
void InitializeSubAllocators ( void );
|
||||
Boolean ReclaimMemory(size_t amountNeeded);
|
||||
long pascal MallocGrowZoneProc(Size cbNeeded);
|
||||
|
||||
#define kMinLargeBlockHeapSize (65 * 1024) /* Min size of the heaps in temp mem try to allocate */
|
||||
#define kMaxLargeBlockHeapSize (1024 * 1024) /* Max size of the heaps in temp mem try to allocate */
|
||||
#define kLargeBlockInitialPercentage (65) /* This is the % of the free space in the heap used for the
|
||||
large block allocation heap */
|
||||
|
||||
#define kMallocLowTempMemoryBoundary (256 * 1024) /* This is a boundary point at which we assume we're
|
||||
running low on temp memory */
|
||||
|
||||
#define kHeapEmergencyReserve (64 * 1024) /* Keep 64k free in the app heap for emergencies */
|
||||
|
||||
|
||||
#if GENERATINGCFM
|
||||
RoutineDescriptor gMallocGrowZoneProcRD = BUILD_ROUTINE_DESCRIPTOR(uppGrowZoneProcInfo, &MallocGrowZoneProc);
|
||||
#else
|
||||
#define gMallocGrowZoneProcRD MallocGrowZoneProc
|
||||
#endif
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark FIXED-SIZE ALLOCATION DECLARATIONS
|
||||
|
||||
/* The format here is:
|
||||
|
||||
DeclareFixedSizeAllocator(blockSize lower bound, # blocks in a heap chunk, # blocks in a tempmem chunk);
|
||||
|
||||
DeclareSmallHeapAllocator(first chunk heap size, temp mem chunk heap size );
|
||||
|
||||
*/
|
||||
|
||||
// the real declarators
|
||||
DeclareFixedSizeAllocator(4, 2600, 1000);
|
||||
DeclareFixedSizeAllocator(8, 2000, 1000);
|
||||
DeclareFixedSizeAllocator(12, 5000, 1000);
|
||||
DeclareFixedSizeAllocator(16, 4000, 1000);
|
||||
DeclareFixedSizeAllocator(20, 7000, 3000);
|
||||
DeclareFixedSizeAllocator(24, 9500, 3000);
|
||||
DeclareFixedSizeAllocator(28, 3200, 1000);
|
||||
DeclareFixedSizeAllocator(32, 3400, 1000);
|
||||
DeclareFixedSizeAllocator(36, 2500, 500);
|
||||
DeclareFixedSizeAllocator(40, 9300, 5000);
|
||||
DeclareSmallHeapAllocator(512 * 1024, 256 * 1024);
|
||||
DeclareLargeBlockAllocator(kLargeBlockInitialPercentage, kMaxLargeBlockHeapSize, kMinLargeBlockHeapSize);
|
||||
|
||||
AllocMemoryBlockDescriptor gFastMemSmallSizeAllocators[] = {
|
||||
DeclareLargeBlockHeapDescriptor(), // 0
|
||||
DeclareFixedBlockHeapDescriptor(4), // 4
|
||||
DeclareFixedBlockHeapDescriptor(8), // 8
|
||||
DeclareFixedBlockHeapDescriptor(12), // 12
|
||||
DeclareFixedBlockHeapDescriptor(16), // 16
|
||||
DeclareFixedBlockHeapDescriptor(20), // 20
|
||||
DeclareFixedBlockHeapDescriptor(24), // 24
|
||||
DeclareFixedBlockHeapDescriptor(28), // 28
|
||||
DeclareFixedBlockHeapDescriptor(32), // 32
|
||||
DeclareFixedBlockHeapDescriptor(36), // 36
|
||||
DeclareFixedBlockHeapDescriptor(40), // 40
|
||||
DeclareSmallSmallHeapDescriptor(), // 44
|
||||
DeclareSmallSmallHeapDescriptor(), // 48
|
||||
DeclareSmallSmallHeapDescriptor(), // 52
|
||||
DeclareSmallSmallHeapDescriptor(), // 56
|
||||
DeclareSmallSmallHeapDescriptor(), // 60
|
||||
DeclareSmallSmallHeapDescriptor(), // 64
|
||||
DeclareSmallSmallHeapDescriptor(), // 68
|
||||
DeclareSmallSmallHeapDescriptor(), // 72
|
||||
DeclareSmallSmallHeapDescriptor(), // 76
|
||||
DeclareSmallSmallHeapDescriptor(), // 80
|
||||
DeclareSmallSmallHeapDescriptor(), // 84
|
||||
DeclareSmallSmallHeapDescriptor(), // 88
|
||||
DeclareSmallSmallHeapDescriptor(), // 92
|
||||
DeclareSmallSmallHeapDescriptor(), // 96
|
||||
DeclareSmallSmallHeapDescriptor(), // 100
|
||||
DeclareSmallSmallHeapDescriptor(), // 104
|
||||
DeclareSmallSmallHeapDescriptor(), // 108
|
||||
DeclareSmallSmallHeapDescriptor(), // 112
|
||||
DeclareSmallSmallHeapDescriptor(), // 116
|
||||
DeclareSmallSmallHeapDescriptor(), // 120
|
||||
DeclareSmallSmallHeapDescriptor(), // 124
|
||||
DeclareSmallSmallHeapDescriptor(), // 128
|
||||
DeclareSmallSmallHeapDescriptor(), // 132
|
||||
DeclareSmallSmallHeapDescriptor(), // 136
|
||||
DeclareSmallSmallHeapDescriptor(), // 140
|
||||
DeclareSmallSmallHeapDescriptor(), // 144
|
||||
DeclareSmallSmallHeapDescriptor(), // 148
|
||||
DeclareSmallSmallHeapDescriptor(), // 152
|
||||
DeclareSmallSmallHeapDescriptor(), // 156
|
||||
DeclareSmallSmallHeapDescriptor(), // 160
|
||||
DeclareSmallSmallHeapDescriptor(), // 164
|
||||
DeclareSmallSmallHeapDescriptor(), // 168
|
||||
DeclareSmallSmallHeapDescriptor(), // 172
|
||||
DeclareSmallSmallHeapDescriptor(), // 176
|
||||
DeclareSmallSmallHeapDescriptor(), // 180
|
||||
DeclareSmallSmallHeapDescriptor(), // 184
|
||||
DeclareSmallSmallHeapDescriptor(), // 188
|
||||
DeclareSmallSmallHeapDescriptor(), // 192
|
||||
DeclareSmallSmallHeapDescriptor(), // 196
|
||||
DeclareSmallSmallHeapDescriptor(), // 200
|
||||
DeclareSmallSmallHeapDescriptor(), // 204
|
||||
DeclareSmallSmallHeapDescriptor(), // 208
|
||||
DeclareSmallSmallHeapDescriptor(), // 212
|
||||
DeclareSmallSmallHeapDescriptor(), // 216
|
||||
DeclareSmallSmallHeapDescriptor(), // 220
|
||||
DeclareSmallSmallHeapDescriptor(), // 224
|
||||
DeclareSmallSmallHeapDescriptor(), // 228
|
||||
DeclareSmallSmallHeapDescriptor(), // 232
|
||||
DeclareSmallSmallHeapDescriptor(), // 236
|
||||
DeclareSmallSmallHeapDescriptor(), // 240
|
||||
DeclareSmallSmallHeapDescriptor(), // 244
|
||||
DeclareSmallSmallHeapDescriptor(), // 248
|
||||
DeclareSmallSmallHeapDescriptor(), // 252
|
||||
DeclareSmallSmallHeapDescriptor(), // 256
|
||||
};
|
||||
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark-
|
||||
#pragma mark INSTRUMENTATION
|
||||
|
||||
#if INSTRUMENT_MAC_MEMORY
|
||||
|
||||
|
||||
InstHistogramClassRef gSmallHeapHistogram = 0;
|
||||
InstHistogramClassRef gLargeHeapHistogram = 0;
|
||||
|
||||
|
||||
static OSErr CreateInstrumentationClasses()
|
||||
{
|
||||
OSErr err = noErr;
|
||||
|
||||
err = InstCreateHistogramClass(kInstRootClassRef, "MacMemAllocator:SmallHeap:Histogram",
|
||||
40, 256, 4, kInstEnableClassMask, &gSmallHeapHistogram);
|
||||
if (err != noErr) return err;
|
||||
|
||||
err = InstCreateHistogramClass(kInstRootClassRef, "MacMemAllocator:LargeHeap:Histogram",
|
||||
256, 10240, 64, kInstEnableClassMask, &gLargeHeapHistogram);
|
||||
if (err != noErr) return err;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark-
|
||||
#pragma mark INITIALIZATION
|
||||
|
||||
void MacintoshInitializeMemory(void)
|
||||
{
|
||||
UInt32 i;
|
||||
ProcessSerialNumber thisProcess = { 0, kCurrentProcess };
|
||||
ProcessInfoRec processInfo;
|
||||
|
||||
// Increase the stack space.
|
||||
// This is because PA_MDL_ParseTag can go into deep recursion when dealing with
|
||||
// malformed HTML comments (the only occurrence where we bombed).
|
||||
#ifndef powerc
|
||||
SetApplLimit(GetApplLimit() - 16384);
|
||||
#endif
|
||||
|
||||
#if !TARGET_CARBON
|
||||
MaxApplZone();
|
||||
#endif
|
||||
|
||||
for (i = 1; i <= 30; i++)
|
||||
MoreMasters();
|
||||
|
||||
// init our new compact allocators
|
||||
|
||||
processInfo.processInfoLength = sizeof(processInfo);
|
||||
processInfo.processName = NULL;
|
||||
processInfo.processAppSpec = NULL;
|
||||
|
||||
GetProcessInformation(&thisProcess, &processInfo);
|
||||
gOurApplicationHeapBase = processInfo.processLocation;
|
||||
gOurApplicationHeapMax = (Ptr)gOurApplicationHeapBase + processInfo.processSize;
|
||||
|
||||
#if INSTRUMENT_MAC_MEMORY
|
||||
if (CreateInstrumentationClasses() != noErr)
|
||||
{
|
||||
DebugStr("\pFailed to initialize instrumentation classes");
|
||||
ExitToShell();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DEBUG_MAC_MEMORY || STATS_MAC_MEMORY
|
||||
InstallMemoryManagerPatches();
|
||||
|
||||
#if DEBUG_MAC_MEMORY
|
||||
// Create some allocation sets to track our allocators
|
||||
gFixedSizeAllocatorSet = NewAllocationSet ( 0, "Fixed Size Compact Allocator" );
|
||||
gSmallHeapAllocatorSet = NewAllocationSet ( 0, "Small Heap Allocator" );
|
||||
gLargeBlockAllocatorSet = NewAllocationSet ( 0, "Large Block Allocator" );
|
||||
|
||||
// disable them so we don't get random garbage
|
||||
DisableAllocationSet ( gFixedSizeAllocatorSet );
|
||||
DisableAllocationSet ( gSmallHeapAllocatorSet );
|
||||
DisableAllocationSet ( gLargeBlockAllocatorSet );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// intialize the sub allocators
|
||||
InitializeSubAllocators();
|
||||
|
||||
gMemoryInitialized = true;
|
||||
}
|
||||
|
||||
void InitializeSubAllocators ( void )
|
||||
{
|
||||
SubHeapAllocationChunk * chunk;
|
||||
|
||||
#ifdef MALLOC_IS_NEWPTR
|
||||
/* Don't allocate memory pools if just using NewPtr */
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* fixed size allocators */
|
||||
chunk = FixedSizeAllocChunk ( 0, &gFixedSize4Root );
|
||||
PR_ASSERT(chunk);
|
||||
if ( chunk == NULL ) goto fail;
|
||||
|
||||
chunk = FixedSizeAllocChunk ( 0, &gFixedSize8Root );
|
||||
PR_ASSERT(chunk);
|
||||
if ( chunk == NULL ) goto fail;
|
||||
|
||||
chunk = FixedSizeAllocChunk ( 0, &gFixedSize12Root );
|
||||
PR_ASSERT(chunk);
|
||||
if ( chunk == NULL ) goto fail;
|
||||
|
||||
chunk = FixedSizeAllocChunk ( 0, &gFixedSize16Root );
|
||||
PR_ASSERT(chunk);
|
||||
if ( chunk == NULL ) goto fail;
|
||||
|
||||
chunk = FixedSizeAllocChunk ( 0, &gFixedSize20Root );
|
||||
PR_ASSERT(chunk);
|
||||
if ( chunk == NULL ) goto fail;
|
||||
|
||||
chunk = FixedSizeAllocChunk ( 0, &gFixedSize24Root );
|
||||
PR_ASSERT(chunk);
|
||||
if ( chunk == NULL ) goto fail;
|
||||
|
||||
chunk = FixedSizeAllocChunk ( 0, &gFixedSize28Root );
|
||||
PR_ASSERT(chunk);
|
||||
if ( chunk == NULL ) goto fail;
|
||||
|
||||
chunk = FixedSizeAllocChunk ( 0, &gFixedSize32Root );
|
||||
PR_ASSERT(chunk);
|
||||
if ( chunk == NULL ) goto fail;
|
||||
|
||||
chunk = FixedSizeAllocChunk ( 0, &gFixedSize36Root );
|
||||
PR_ASSERT(chunk);
|
||||
if ( chunk == NULL ) goto fail;
|
||||
|
||||
chunk = FixedSizeAllocChunk ( 0, &gFixedSize40Root );
|
||||
PR_ASSERT(chunk);
|
||||
if ( chunk == NULL ) goto fail;
|
||||
|
||||
chunk = SmallHeapAllocChunk ( 0, &gSmallHeapRoot );
|
||||
PR_ASSERT(chunk);
|
||||
if ( chunk == NULL ) goto fail;
|
||||
|
||||
chunk = LargeBlockAllocChunk ( 0, &gLargeBlockRoot );
|
||||
PR_ASSERT(chunk);
|
||||
if ( chunk == NULL ) goto fail;
|
||||
|
||||
#if DEBUG_MAC_MEMORY && TRACK_EACH_ALLOCATOR
|
||||
gFixedSize4Root.header.set = NewAllocationSet ( 0, "Fixed Block 4" );
|
||||
DisableAllocationSet ( gFixedSize4Root.header.set );
|
||||
|
||||
gFixedSize8Root.header.set = NewAllocationSet ( 0, "Fixed Block 8" );
|
||||
DisableAllocationSet ( gFixedSize8Root.header.set );
|
||||
|
||||
gFixedSize12Root.header.set = NewAllocationSet ( 0, "Fixed Block 12" );
|
||||
DisableAllocationSet ( gFixedSize12Root.header.set );
|
||||
|
||||
gFixedSize16Root.header.set = NewAllocationSet ( 0, "Fixed Block 16" );
|
||||
DisableAllocationSet ( gFixedSize16Root.header.set );
|
||||
|
||||
gFixedSize20Root.header.set = NewAllocationSet ( 0, "Fixed Block 20" );
|
||||
DisableAllocationSet ( gFixedSize20Root.header.set );
|
||||
|
||||
gFixedSize24Root.header.set = NewAllocationSet ( 0, "Fixed Block 24" );
|
||||
DisableAllocationSet ( gFixedSize24Root.header.set );
|
||||
|
||||
gFixedSize28Root.header.set = NewAllocationSet ( 0, "Fixed Block 28" );
|
||||
DisableAllocationSet ( gFixedSize28Root.header.set );
|
||||
|
||||
gFixedSize32Root.header.set = NewAllocationSet ( 0, "Fixed Block 32" );
|
||||
DisableAllocationSet ( gFixedSize32Root.header.set );
|
||||
|
||||
gFixedSize36Root.header.set = NewAllocationSet ( 0, "Fixed Block 36" );
|
||||
DisableAllocationSet ( gFixedSize36Root.header.set );
|
||||
|
||||
gFixedSize40Root.header.set = NewAllocationSet ( 0, "Fixed Block 40" );
|
||||
DisableAllocationSet ( gFixedSize40Root.header.set );
|
||||
|
||||
gSmallHeapRoot.header.set = NewAllocationSet ( 0, "Small Block" );
|
||||
DisableAllocationSet ( gSmallHeapRoot.header.set );
|
||||
|
||||
gLargeBlockRoot.header.set = NewAllocationSet ( 0, "Large Block" );
|
||||
DisableAllocationSet ( gLargeBlockRoot.header.set );
|
||||
#endif
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
/* We couldn't initialize one of the sub allocators, so we're screwed */
|
||||
/* I don't think we need an alert here as we should never hit this case unless */
|
||||
/* a user really mucks up our heap partition */
|
||||
ExitToShell();
|
||||
}
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
|
||||
/* I hate copy and paste */
|
||||
static void WriteString ( PRFileHandle file, const char * string )
|
||||
{
|
||||
long len;
|
||||
long bytesWritten;
|
||||
|
||||
len = strlen( string );
|
||||
if ( len >= 1024 ) Debugger();
|
||||
bytesWritten = _OS_WRITE ( file, string, len );
|
||||
PR_ASSERT(bytesWritten == len);
|
||||
}
|
||||
|
||||
static void WriteFixedAllocatorStats(PRFileHandle outFile, const FixedSizeAllocationRoot *root)
|
||||
{
|
||||
char outString[ 1024 ];
|
||||
|
||||
WriteString ( outFile, "--------------------------------------------------------------------------------\n" );
|
||||
|
||||
sprintf(outString, "Stats for fixed size allocator for blocks of %d-%d bytes\n", root->blockSize - 3, root->blockSize);
|
||||
WriteString ( outFile, outString );
|
||||
|
||||
WriteString ( outFile, "--------------------------------------------------------------------------------\n" );
|
||||
|
||||
WriteString ( outFile, " Current Max\n" );
|
||||
WriteString ( outFile, " ---------- -------\n" );
|
||||
|
||||
sprintf( outString, "Num chunks: %10d %10d\n", root->chunksAllocated, root->maxChunksAllocated );
|
||||
WriteString ( outFile, outString );
|
||||
|
||||
sprintf( outString, "Chunk total: %10d %10d\n", root->totalChunkSize, root->maxTotalChunkSize );
|
||||
WriteString ( outFile, outString );
|
||||
|
||||
sprintf( outString, "Num blocks: %10d %10d\n", root->blocksAllocated, root->maxBlocksAllocated );
|
||||
WriteString ( outFile, outString );
|
||||
|
||||
sprintf( outString, "Block space: %10d %10d\n", root->blockSpaceUsed, root->maxBlockSpaceUsed );
|
||||
WriteString ( outFile, outString );
|
||||
|
||||
sprintf( outString, "Blocks used: %10d %10d\n", root->blocksUsed, root->maxBlocksUsed );
|
||||
WriteString ( outFile, outString );
|
||||
|
||||
WriteString ( outFile, " -------\n" );
|
||||
|
||||
sprintf( outString, "%s of allocated blocks used: %10.2f\n", "%", 100.0 * root->maxBlocksUsed / root->maxBlocksAllocated );
|
||||
WriteString ( outFile, outString );
|
||||
|
||||
sprintf( outString, "%s of chunk space used: %10.2f\n", "%", 100.0 * root->maxBlockSpaceUsed / root->maxTotalChunkSize );
|
||||
WriteString ( outFile, outString );
|
||||
|
||||
WriteString ( outFile, "\n\n");
|
||||
}
|
||||
|
||||
void DumpAllocatorMemoryStats(PRFileHandle outFile);
|
||||
|
||||
void DumpAllocatorMemoryStats(PRFileHandle outFile)
|
||||
{
|
||||
/* fixed size allocators */
|
||||
WriteFixedAllocatorStats( outFile, &gFixedSize4Root );
|
||||
WriteFixedAllocatorStats( outFile, &gFixedSize8Root );
|
||||
WriteFixedAllocatorStats( outFile, &gFixedSize12Root );
|
||||
WriteFixedAllocatorStats( outFile, &gFixedSize16Root );
|
||||
WriteFixedAllocatorStats( outFile, &gFixedSize20Root );
|
||||
WriteFixedAllocatorStats( outFile, &gFixedSize24Root );
|
||||
WriteFixedAllocatorStats( outFile, &gFixedSize32Root );
|
||||
WriteFixedAllocatorStats( outFile, &gFixedSize36Root );
|
||||
WriteFixedAllocatorStats( outFile, &gFixedSize40Root );
|
||||
|
||||
/*
|
||||
chunk = SmallHeapAllocChunk ( 0, &gSmallHeapRoot );
|
||||
PR_ASSERT(chunk);
|
||||
if ( chunk == NULL ) goto fail;
|
||||
|
||||
chunk = LargeBlockAllocChunk ( 0, &gLargeBlockRoot );
|
||||
PR_ASSERT(chunk);
|
||||
if ( chunk == NULL ) goto fail;
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
#endif /* STATS_MAC_MEMORY */
|
||||
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark INSTALLING MEMORY MANAGER HOOKS
|
||||
|
||||
void InstallPreAllocationHook(PreAllocationHookProc newHook)
|
||||
{
|
||||
PreAllocationProcRec *preAllocatorRec;
|
||||
|
||||
preAllocatorRec = (PreAllocationProcRec *)(NewPtr(sizeof(PreAllocationProcRec)));
|
||||
|
||||
if (preAllocatorRec != NULL) {
|
||||
|
||||
preAllocatorRec->next = gFirstPreAllocator;
|
||||
preAllocatorRec->preAllocProc = newHook;
|
||||
gFirstPreAllocator = preAllocatorRec;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void InstallMemoryCacheFlusher(MemoryCacheFlusherProc newFlusher)
|
||||
{
|
||||
MemoryCacheFlusherProcRec *previousFlusherRec = NULL;
|
||||
MemoryCacheFlusherProcRec *cacheFlusherRec = gFirstFlusher;
|
||||
|
||||
while (cacheFlusherRec != NULL) {
|
||||
previousFlusherRec = cacheFlusherRec;
|
||||
cacheFlusherRec = cacheFlusherRec->next;
|
||||
}
|
||||
|
||||
cacheFlusherRec = (MemoryCacheFlusherProcRec *)NewPtrClear(sizeof(MemoryCacheFlusherProcRec));
|
||||
|
||||
if (cacheFlusherRec == NULL)
|
||||
return;
|
||||
|
||||
cacheFlusherRec->flushProc = newFlusher;
|
||||
|
||||
if (previousFlusherRec != NULL) {
|
||||
previousFlusherRec->next = cacheFlusherRec;
|
||||
}
|
||||
|
||||
else {
|
||||
gFirstFlusher = cacheFlusherRec;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CallPreAllocators(void)
|
||||
{
|
||||
PreAllocationProcRec *currentPreAllocator = gFirstPreAllocator;
|
||||
|
||||
while (currentPreAllocator != NULL) {
|
||||
(*(currentPreAllocator->preAllocProc))();
|
||||
currentPreAllocator = currentPreAllocator->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static MemoryCacheFlusherProc sGarbageCollectorCacheFlusher = NULL;
|
||||
|
||||
/* CallCacheFlushers is only called under extreme conditions now, when an attempt to
|
||||
allocate a new sub-heap has failed.
|
||||
|
||||
The flush procs called here are set up in fredmem.cp:
|
||||
|
||||
InstallMemoryCacheFlusher(&ImageCacheMemoryFlusher);
|
||||
InstallMemoryCacheFlusher(&NetlibCacheMemoryFlusher);
|
||||
InstallMemoryCacheFlusher(&LayoutCacheMemoryFlusher);
|
||||
InstallMemoryCacheFlusher(&LibNeoCacheMemoryFlusher);
|
||||
|
||||
*/
|
||||
UInt8 CallCacheFlushers(size_t blockSize)
|
||||
{
|
||||
MemoryCacheFlusherProcRec *currentCacheFlusher = gFirstFlusher;
|
||||
UInt8 result = false;
|
||||
|
||||
// we might want to remember which flusher was called last and start
|
||||
// at the one after, to avoid always flushing the first one (image cache)
|
||||
// first. But since this is a last-ditch effort to free memory, that's
|
||||
// probably not worth it.
|
||||
|
||||
while (currentCacheFlusher != NULL)
|
||||
{
|
||||
result |= (*(currentCacheFlusher->flushProc))(blockSize);
|
||||
currentCacheFlusher = currentCacheFlusher->next;
|
||||
}
|
||||
|
||||
// We used to try calling the GC if malloc failed, but that's
|
||||
// a waste of time since the GC never frees segments (bug?)
|
||||
// and thus won't increase heap space.
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
void InstallGarbageCollectorCacheFlusher(const MemoryCacheFlusherProc inFlusher)
|
||||
{
|
||||
sGarbageCollectorCacheFlusher = inFlusher;
|
||||
}
|
||||
|
||||
void InstallMallocHeapLowProc( MallocHeapLowWarnProc proc )
|
||||
{
|
||||
gMallocLowProc = proc;
|
||||
}
|
||||
|
||||
void CallFE_LowMemory(void)
|
||||
{
|
||||
if ( gMallocLowProc != NULL )
|
||||
{
|
||||
gMallocLowProc();
|
||||
}
|
||||
}
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark SUB HEAP ALLOCATION
|
||||
|
||||
SubHeapAllocationChunk * AllocateSubHeap ( SubHeapAllocationRoot * root, Size heapSize, Boolean useTemp )
|
||||
{
|
||||
SubHeapAllocationChunk * heapBlock;
|
||||
Handle tempHandle;
|
||||
OSErr err;
|
||||
|
||||
heapBlock = NULL;
|
||||
tempHandle = NULL;
|
||||
|
||||
#if DEBUG_MAC_MEMORY
|
||||
DisableMemoryTracker();
|
||||
#endif
|
||||
|
||||
if ( useTemp )
|
||||
{
|
||||
tempHandle = TempNewHandle ( heapSize, &err );
|
||||
|
||||
if ( tempHandle == NULL )
|
||||
{
|
||||
// failed to make temp handle. Let's try a handle in our heap
|
||||
tempHandle = NewHandle( heapSize );
|
||||
|
||||
// ensure that enough free mem is available for emergencies
|
||||
if ( tempHandle != NULL && MaxBlock() < kHeapEmergencyReserve)
|
||||
{
|
||||
// we need to keep some contiguous space free for emergencies. Give up.
|
||||
DisposeHandle(tempHandle);
|
||||
tempHandle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ( tempHandle != NULL && err == noErr )
|
||||
{
|
||||
HLockHi ( tempHandle ); // lock the handle hi now to reduce system heap fragmentation
|
||||
heapBlock = *(SubHeapAllocationChunk **) tempHandle;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
heapBlock = (SubHeapAllocationChunk *) NewPtr ( heapSize );
|
||||
}
|
||||
|
||||
if ( heapBlock != NULL )
|
||||
{
|
||||
heapBlock->root = root;
|
||||
heapBlock->refCon = tempHandle; // so we can dispose the handle when we're done with the subheap
|
||||
heapBlock->next = NULL;
|
||||
heapBlock->usedBlocks = 0;
|
||||
heapBlock->freeDescriptor.freeRoutine = NULL;
|
||||
heapBlock->freeDescriptor.refcon = NULL;
|
||||
|
||||
// whack this on the root's chunk list
|
||||
if ( root->lastChunk == NULL )
|
||||
{
|
||||
root->firstChunk = heapBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
root->lastChunk->next = heapBlock;
|
||||
}
|
||||
|
||||
root->lastChunk = heapBlock;
|
||||
}
|
||||
|
||||
#if DEBUG_MAC_MEMORY
|
||||
EnableMemoryTracker();
|
||||
#endif
|
||||
|
||||
return heapBlock;
|
||||
}
|
||||
|
||||
|
||||
void FreeSubHeap ( SubHeapAllocationRoot * root, SubHeapAllocationChunk * chunk )
|
||||
{
|
||||
Handle tempHandle;
|
||||
SubHeapAllocationChunk * list;
|
||||
SubHeapAllocationChunk * prev;
|
||||
SubHeapAllocationChunk * next;
|
||||
|
||||
if ( chunk != NULL )
|
||||
{
|
||||
// run through the root's chunk list and remove our block
|
||||
prev = NULL;
|
||||
list = root->firstChunk;
|
||||
|
||||
while ( list != NULL )
|
||||
{
|
||||
next = list->next;
|
||||
|
||||
if ( list == chunk )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
prev = list;
|
||||
list = next;
|
||||
}
|
||||
|
||||
if ( list != NULL )
|
||||
{
|
||||
if ( prev != NULL )
|
||||
{
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
if ( root->firstChunk == list )
|
||||
{
|
||||
root->firstChunk = next;
|
||||
}
|
||||
|
||||
if ( root->lastChunk == list )
|
||||
{
|
||||
root->lastChunk = prev;
|
||||
}
|
||||
}
|
||||
|
||||
tempHandle = (Handle) chunk->refCon;
|
||||
if ( tempHandle != NULL )
|
||||
{
|
||||
DisposeHandle ( tempHandle );
|
||||
}
|
||||
else
|
||||
{
|
||||
DisposePtr ( (Ptr) chunk );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark MEMORY UTILS
|
||||
|
||||
Boolean gInMemory_ReserveInMacHeap = false;
|
||||
|
||||
Boolean InMemory_ReserveInMacHeap()
|
||||
{
|
||||
return gInMemory_ReserveInMacHeap;
|
||||
}
|
||||
|
||||
Boolean ReclaimMemory(size_t amountNeeded)
|
||||
{
|
||||
Boolean result;
|
||||
|
||||
result = CallCacheFlushers(amountNeeded);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
Boolean Memory_ReserveInMacHeap(size_t spaceNeeded)
|
||||
{
|
||||
Boolean result = true;
|
||||
|
||||
gInMemory_ReserveInMacHeap = true;
|
||||
|
||||
if (MaxBlock() < spaceNeeded)
|
||||
result = ReclaimMemory(spaceNeeded);
|
||||
|
||||
gInMemory_ReserveInMacHeap = false;
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
Boolean Memory_ReserveInMallocHeap(size_t spaceNeeded)
|
||||
{
|
||||
Boolean result = true;
|
||||
Size freeMem;
|
||||
|
||||
gInMemory_ReserveInMacHeap = true;
|
||||
|
||||
freeMem = MaxBlock();
|
||||
|
||||
if (freeMem < spaceNeeded)
|
||||
result = ReclaimMemory(spaceNeeded);
|
||||
|
||||
gInMemory_ReserveInMacHeap = false;
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
size_t Memory_FreeMemoryRemaining()
|
||||
{
|
||||
size_t mainHeap;
|
||||
size_t mallocHeap;
|
||||
|
||||
mainHeap = FreeMem();
|
||||
|
||||
mallocHeap = FreeMem();
|
||||
|
||||
return (mainHeap < mallocHeap) ? mainHeap : mallocHeap;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,387 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <Types.h>
|
||||
#include <Memory.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#pragma error "This file is obsolete, but remains for reference reasons"
|
||||
|
||||
#include "MacMemAllocator.h"
|
||||
|
||||
/* You probably only want to use this for debugging. It's useful to see leaks
|
||||
with ZoneRanger.
|
||||
*/
|
||||
/* #define MALLOC_IS_NEWPTR 1 */
|
||||
|
||||
/* Turn this on to check for block overwrites, heap corruption, bad frees, etc */
|
||||
#define DEBUG_HEAP_INTEGRITY DEBUG
|
||||
|
||||
/* Turn this on to track memory allocations. If you do this, you will have to
|
||||
allocate a lot more memory to the app (symptoms of too little are bogus
|
||||
shared library errors on startup)
|
||||
*/
|
||||
#define DEBUG_MAC_MEMORY 0
|
||||
|
||||
/* This setting is really obsoleted by STATS_MAC_MEMORY, which gives better stats */
|
||||
#define TRACK_EACH_ALLOCATOR 0
|
||||
|
||||
/* Turn this on to track amount of memory allocated and performance of the allocators
|
||||
If you turn this on, it's better to not define DEBUG_HEAP_INTEGRITY, because
|
||||
that setting causes each allocation to be 8-12 bytes larger, which messes
|
||||
up the stats. I've been careful with STATS_MAC_MEMORY to not have it affect
|
||||
block size at all.
|
||||
|
||||
STATS_MAC_MEMORY can be turned on independently of the other debugging settings.
|
||||
It will cause the creation of a text file, "MemoryStats.txt", in the app
|
||||
directory, on quit. Its overhead is very low.
|
||||
*/
|
||||
#define STATS_MAC_MEMORY 0
|
||||
|
||||
/* Turn this on to use Apple's Instrumentation Lib to instrument block allocations
|
||||
Currently, it collects histogram data on the frequency of allocations of
|
||||
different sizes for the small and large allocators.
|
||||
*/
|
||||
/* #define INSTRUMENT_MAC_MEMORY 1 */
|
||||
|
||||
#if INSTRUMENT_MAC_MEMORY
|
||||
#include "Instrumentation.h"
|
||||
#include "InstrumentationMacros.h"
|
||||
#endif
|
||||
|
||||
#if DEBUG_MAC_MEMORY
|
||||
#include "xp_tracker.h"
|
||||
#endif
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
|
||||
|
||||
typedef struct SubHeapAllocationRoot SubHeapAllocationRoot;
|
||||
typedef struct SubHeapAllocationChunk SubHeapAllocationChunk;
|
||||
|
||||
enum {
|
||||
kMaxTableAllocatedBlockSize = 256
|
||||
};
|
||||
|
||||
typedef void *(* AllocMemoryBlockProcPtr)(size_t blockSize, void *refcon);
|
||||
typedef void (* FreeMemoryBlockProcPtr)(void *freeBlock, void *refcon);
|
||||
typedef size_t (* BlockSizeProcPtr)(void *freeBlock, void *refcon);
|
||||
typedef void (* HeapFreeSpaceProcPtr)(size_t blockSize, FreeMemoryStats * stats, void *refcon);
|
||||
typedef SubHeapAllocationChunk * (* AllocMemoryChunkProcPtr)(size_t blockSize, void *refcon);
|
||||
|
||||
struct AllocMemoryBlockDescriptor {
|
||||
AllocMemoryBlockProcPtr blockAllocRoutine;
|
||||
AllocMemoryChunkProcPtr chunkAllocRoutine;
|
||||
HeapFreeSpaceProcPtr heapFreeSpaceRoutine;
|
||||
SubHeapAllocationRoot *root;
|
||||
};
|
||||
|
||||
typedef struct AllocMemoryBlockDescriptor AllocMemoryBlockDescriptor;
|
||||
|
||||
struct FreeMemoryBlockDescriptor {
|
||||
FreeMemoryBlockProcPtr freeRoutine;
|
||||
BlockSizeProcPtr sizeRoutine;
|
||||
void *refcon;
|
||||
};
|
||||
|
||||
typedef struct FreeMemoryBlockDescriptor FreeMemoryBlockDescriptor;
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
typedef UInt32 MemoryBlockTag;
|
||||
#endif
|
||||
|
||||
typedef struct MemoryBlockHeader MemoryBlockHeader;
|
||||
|
||||
struct MemoryBlockHeader {
|
||||
FreeMemoryBlockDescriptor *blockFreeRoutine;
|
||||
#if DEBUG_HEAP_INTEGRITY // || STATS_MAC_MEMORY -- see comment in DumpMemoryStats()
|
||||
size_t blockSize;
|
||||
#endif
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MemoryBlockTag headerTag;
|
||||
MemoryBlockHeader *next;
|
||||
MemoryBlockHeader *prev;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
typedef struct MemoryBlockTrailer MemoryBlockTrailer;
|
||||
|
||||
struct MemoryBlockTrailer {
|
||||
MemoryBlockTag trailerTag;
|
||||
};
|
||||
#define MEMORY_BLOCK_TAILER_SIZE sizeof(struct MemoryBlockTrailer)
|
||||
#else
|
||||
#define MEMORY_BLOCK_TAILER_SIZE 0
|
||||
#endif
|
||||
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark SUB HEAP ALLOCATOR
|
||||
|
||||
struct SubHeapAllocationRoot {
|
||||
SubHeapAllocationChunk * firstChunk;
|
||||
SubHeapAllocationChunk * lastChunk;
|
||||
#if DEBUG_MAC_MEMORY && TRACK_EACH_ALLOCATOR
|
||||
AllocationSet * set;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct SubHeapAllocationChunk {
|
||||
SubHeapAllocationRoot * root;
|
||||
SubHeapAllocationChunk * next;
|
||||
void * refCon;
|
||||
SInt32 usedBlocks;
|
||||
UInt32 heapSize;
|
||||
FreeMemoryBlockDescriptor freeDescriptor;
|
||||
};
|
||||
|
||||
// The following two entry points for sub heap allocations
|
||||
extern SubHeapAllocationChunk * AllocateSubHeap ( SubHeapAllocationRoot * root, Size heapSize, Boolean useTemp );
|
||||
extern void FreeSubHeap ( SubHeapAllocationRoot * root, SubHeapAllocationChunk * chunk );
|
||||
|
||||
#if DEBUG_MAC_MEMORY && TRACK_EACH_ALLOCATOR
|
||||
#define DECLARE_SUBHEAP_ROOT() { NULL, NULL, NULL }
|
||||
#else
|
||||
#define DECLARE_SUBHEAP_ROOT() { NULL, NULL }
|
||||
#endif
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark LARGE BLOCK ALLOCATOR
|
||||
|
||||
typedef struct LargeBlockHeader LargeBlockHeader;
|
||||
|
||||
struct LargeBlockHeader {
|
||||
LargeBlockHeader * next;
|
||||
LargeBlockHeader * prev;
|
||||
size_t logicalSize;
|
||||
MemoryBlockHeader header;
|
||||
};
|
||||
|
||||
typedef struct LargeBlockAllocationChunk LargeBlockAllocationChunk;
|
||||
|
||||
typedef struct LargeBlockAllocationRoot LargeBlockAllocationRoot;
|
||||
|
||||
struct LargeBlockAllocationChunk {
|
||||
SubHeapAllocationChunk header;
|
||||
UInt32 totalFree;
|
||||
LargeBlockHeader * tail;
|
||||
LargeBlockHeader head[];
|
||||
};
|
||||
|
||||
struct LargeBlockAllocationRoot {
|
||||
SubHeapAllocationRoot header;
|
||||
UInt32 baseChunkPercentage;
|
||||
UInt32 idealTempChunkSize;
|
||||
UInt32 smallestTempChunkSize;
|
||||
};
|
||||
|
||||
void *LargeBlockAlloc(size_t blockSize, void *refcon);
|
||||
void LargeBlockFree(void *block, void *refcon);
|
||||
SubHeapAllocationChunk * LargeBlockAllocChunk ( size_t blockSize, void *refcon );
|
||||
size_t LargeBlockSize (void *freeBlock, void *refcon);
|
||||
void LargeBlockHeapFree(size_t blockSize, FreeMemoryStats * stats, void * refcon);
|
||||
|
||||
extern LargeBlockAllocationRoot gLargeBlockRoot;
|
||||
|
||||
#define DeclareLargeBlockAllocator(basePercentage,idealTmpSize,smallestTmpSize) \
|
||||
LargeBlockAllocationRoot gLargeBlockRoot = { DECLARE_SUBHEAP_ROOT(), basePercentage, idealTmpSize, smallestTmpSize }
|
||||
|
||||
#define DeclareLargeBlockHeapDescriptor() \
|
||||
{ &LargeBlockAlloc, &LargeBlockAllocChunk, &LargeBlockHeapFree, (SubHeapAllocationRoot *)&gLargeBlockRoot }
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark FIXED SIZED ALLOCATOR DEFINITIONS
|
||||
|
||||
typedef struct FixedMemoryFreeBlockHeader FixedMemoryFreeBlockHeader;
|
||||
|
||||
struct FixedMemoryFreeBlockHeader {
|
||||
MemoryBlockHeader header;
|
||||
FixedMemoryFreeBlockHeader * next;
|
||||
};
|
||||
|
||||
typedef struct FixedSizeAllocationChunk FixedSizeAllocationChunk;
|
||||
|
||||
typedef struct FixedSizeAllocationRoot FixedSizeAllocationRoot;
|
||||
|
||||
struct FixedSizeAllocationChunk {
|
||||
SubHeapAllocationChunk header;
|
||||
#if STATS_MAC_MEMORY
|
||||
UInt32 chunkSize;
|
||||
UInt32 numBlocks;
|
||||
#endif
|
||||
FixedMemoryFreeBlockHeader * freeList;
|
||||
FixedMemoryFreeBlockHeader memory[];
|
||||
};
|
||||
|
||||
struct FixedSizeAllocationRoot {
|
||||
SubHeapAllocationRoot header;
|
||||
UInt32 baseChunkBlockCount;
|
||||
UInt32 tempChunkBlockCount;
|
||||
UInt32 blockSize;
|
||||
#if STATS_MAC_MEMORY
|
||||
UInt32 chunksAllocated;
|
||||
UInt32 maxChunksAllocated;
|
||||
|
||||
UInt32 totalChunkSize;
|
||||
UInt32 maxTotalChunkSize;
|
||||
|
||||
UInt32 blocksAllocated;
|
||||
UInt32 maxBlocksAllocated;
|
||||
|
||||
UInt32 blocksUsed;
|
||||
UInt32 maxBlocksUsed;
|
||||
|
||||
UInt32 blockSpaceUsed;
|
||||
UInt32 maxBlockSpaceUsed;
|
||||
#endif
|
||||
};
|
||||
|
||||
void *FixedSizeAlloc(size_t blockSize, void *refcon);
|
||||
void FixedSizeFree(void *block, void *refcon);
|
||||
SubHeapAllocationChunk * FixedSizeAllocChunk ( size_t blockSize, void *refcon );
|
||||
size_t FixedBlockSize (void *freeBlock, void *refcon);
|
||||
void FixedBlockHeapFree(size_t blockSize, FreeMemoryStats * stats, void * refcon);
|
||||
|
||||
/* When STATS_MAC_MEMORY, the extra fields in the FixedSizeAllocationRoot will be zeroed on initialization */
|
||||
#define DeclareFixedSizeAllocator(blockSize,baseCount,tempCount) \
|
||||
extern FixedSizeAllocationRoot gFixedSize##blockSize##Root; \
|
||||
FixedSizeAllocationRoot gFixedSize##blockSize##Root = { DECLARE_SUBHEAP_ROOT(), baseCount, tempCount, blockSize }
|
||||
|
||||
#define DeclareFixedBlockHeapDescriptor(blockSize) \
|
||||
{ &FixedSizeAlloc, &FixedSizeAllocChunk, &FixedBlockHeapFree, (SubHeapAllocationRoot *)&gFixedSize##blockSize##Root }
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark SMALL HEAP ALLOCATOR DEFINITIONS
|
||||
|
||||
typedef struct SmallHeapBlock SmallHeapBlock;
|
||||
|
||||
struct SmallHeapBlock {
|
||||
SmallHeapBlock *prevBlock;
|
||||
UInt32 blockSize;
|
||||
union {
|
||||
struct {
|
||||
SmallHeapBlock *nextFree;
|
||||
SmallHeapBlock *prevFree;
|
||||
} freeInfo;
|
||||
struct {
|
||||
UInt32 filler;
|
||||
MemoryBlockHeader freeProc;
|
||||
} inUseInfo;
|
||||
} info;
|
||||
};
|
||||
|
||||
enum {
|
||||
kBlockInUseFlag = 0x80000000,
|
||||
kDefaultSmallHeadMinSize = 4L,
|
||||
kDefaultSmallHeapBins = 64L,
|
||||
kMaximumBinBlockSize = kDefaultSmallHeadMinSize + 4L * kDefaultSmallHeapBins - 1
|
||||
};
|
||||
|
||||
typedef struct SmallHeapChunk SmallHeapChunk;
|
||||
|
||||
typedef struct SmallHeapRoot SmallHeapRoot;
|
||||
|
||||
struct SmallHeapRoot {
|
||||
SubHeapAllocationRoot header;
|
||||
UInt32 baseChunkHeapSize;
|
||||
UInt32 tempChunkHeapSize;
|
||||
};
|
||||
|
||||
struct SmallHeapChunk {
|
||||
SubHeapAllocationChunk header;
|
||||
SmallHeapChunk * nextChunk;
|
||||
SmallHeapBlock * overflow;
|
||||
SmallHeapBlock * bins[kDefaultSmallHeapBins];
|
||||
SmallHeapBlock memory[];
|
||||
};
|
||||
|
||||
#define DeclareSmallHeapAllocator(baseSize, tempSize) \
|
||||
extern SmallHeapRoot gSmallHeapRoot; \
|
||||
SmallHeapRoot gSmallHeapRoot = { DECLARE_SUBHEAP_ROOT(), baseSize, tempSize }
|
||||
|
||||
#define DeclareSmallSmallHeapDescriptor() \
|
||||
{ &SmallHeapAlloc, &SmallHeapAllocChunk, &SmallBlockHeapFree, (SubHeapAllocationRoot *)&gSmallHeapRoot }
|
||||
|
||||
void *SmallHeapAlloc(size_t blockSize, void *refcon);
|
||||
void SmallHeapFree(void *address, void *refcon);
|
||||
SubHeapAllocationChunk * SmallHeapAllocChunk ( size_t blockSize, void *refcon );
|
||||
size_t SmallBlockSize (void *freeBlock, void *refcon);
|
||||
void SmallBlockHeapFree(size_t blockSize, FreeMemoryStats * stats, void * refcon);
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark LOW LEVEL ALLOCATORS
|
||||
|
||||
// Client Provides a table to small block allocators
|
||||
extern AllocMemoryBlockDescriptor gFastMemSmallSizeAllocators[];
|
||||
|
||||
// VerifyMallocHeapIntegrity will report any block headers or
|
||||
// trailers that have been overwritten.
|
||||
extern void InstallMemoryManagerPatches();
|
||||
extern void VerifyMallocHeapIntegrity();
|
||||
static void TagReferencedBlocks();
|
||||
extern void DumpMemoryStats();
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
|
||||
#ifdef DEBUG_HEAP_INTEGRITY
|
||||
|
||||
extern UInt32 gVerifyHeapOnEveryMalloc;
|
||||
extern UInt32 gVerifyHeapOnEveryFree;
|
||||
extern UInt32 gFillUsedBlocksWithPattern;
|
||||
extern UInt32 gFillFreeBlocksWithPattern;
|
||||
extern UInt32 gDontActuallyFreeMemory;
|
||||
extern SInt32 gFailToAllocateAfterNMallocs;
|
||||
|
||||
extern SInt32 gTagReferencedBlocks;
|
||||
#endif
|
||||
|
||||
#if INSTRUMENT_MAC_MEMORY
|
||||
extern InstHistogramClassRef gSmallHeapHistogram;
|
||||
extern InstHistogramClassRef gLargeHeapHistogram;
|
||||
#endif
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,296 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#pragma error "This file is obsolete, but remains for reference reasons"
|
||||
|
||||
|
||||
#include <Types.h>
|
||||
#include <Memory.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DEBUG_MAC_MEMORY 0
|
||||
#define STATS_MAC_MEMORY 0
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
|
||||
enum {
|
||||
kMaxTableAllocatedBlockSize = 256,
|
||||
kRecordingDepthOfStackLevels = 3
|
||||
};
|
||||
|
||||
typedef void *(* AllocMemoryBlockProcPtr)(size_t blockSize, void *refcon);
|
||||
typedef void (* FreeMemoryBlockProcPtr)(void *freeBlock, void *refcon);
|
||||
|
||||
struct AllocMemoryBlockDescriptor {
|
||||
AllocMemoryBlockProcPtr allocRoutine;
|
||||
void *refcon;
|
||||
};
|
||||
|
||||
typedef struct AllocMemoryBlockDescriptor AllocMemoryBlockDescriptor;
|
||||
|
||||
struct FreeMemoryBlockDescriptor {
|
||||
FreeMemoryBlockProcPtr freeRoutine;
|
||||
void *refcon;
|
||||
};
|
||||
|
||||
typedef struct FreeMemoryBlockDescriptor FreeMemoryBlockDescriptor;
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
|
||||
#if DEBUG_MAC_MEMORY
|
||||
typedef UInt32 MemoryBlockTag;
|
||||
#endif
|
||||
|
||||
typedef struct MemoryBlockHeader MemoryBlockHeader;
|
||||
|
||||
struct MemoryBlockHeader {
|
||||
FreeMemoryBlockDescriptor *blockFreeRoutine;
|
||||
#if DEBUG_MAC_MEMORY || STATS_MAC_MEMORY
|
||||
size_t blockSize;
|
||||
#endif
|
||||
#if DEBUG_MAC_MEMORY
|
||||
MemoryBlockHeader *next;
|
||||
MemoryBlockHeader *prev;
|
||||
UInt32 blockNum;
|
||||
void *whoAllocated[kRecordingDepthOfStackLevels];
|
||||
MemoryBlockTag headerTag;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if DEBUG_MAC_MEMORY
|
||||
typedef struct MemoryBlockTrailer MemoryBlockTrailer;
|
||||
|
||||
struct MemoryBlockTrailer {
|
||||
MemoryBlockTag trailerTag;
|
||||
};
|
||||
#define MEMORY_BLOCK_TAILER_SIZE sizeof(struct MemoryBlockTrailer)
|
||||
#else
|
||||
#define MEMORY_BLOCK_TAILER_SIZE 0
|
||||
#endif
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark STANDARD (SLOW!) ALLOCATOR DEFINITIONS
|
||||
|
||||
void *StandardAlloc(size_t blockSize, void *refcon);
|
||||
void StandardFree(void *block, void *refcon);
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark FIXED SIZED (COMPACT) ALLOCATOR DEFINITIONS
|
||||
|
||||
typedef struct FixedSizeCompactAllocationChunk FixedSizeCompactAllocationChunk;
|
||||
|
||||
typedef struct FixedSizeCompactAllocationRoot FixedSizeCompactAllocationRoot;
|
||||
|
||||
struct FixedSizeCompactAllocationChunk {
|
||||
FixedSizeCompactAllocationChunk *next;
|
||||
FixedSizeCompactAllocationRoot *root;
|
||||
UInt32 chunkUsage;
|
||||
};
|
||||
|
||||
|
||||
struct FixedSizeCompactAllocationRoot {
|
||||
FixedSizeCompactAllocationChunk *firstChunk;
|
||||
UInt32 blockSize;
|
||||
FreeMemoryBlockDescriptor *freeDescriptorTable;
|
||||
};
|
||||
|
||||
void *FixedSizeCompactAlloc(size_t blockSize, void *refcon);
|
||||
void FixedSizeCompactFree(void *block, void *refcon);
|
||||
|
||||
#define DeclareFixedSizeCompactAllocator(blockSize) \
|
||||
FreeMemoryBlockDescriptor FixedSizeCompact##blockSize##AllocationFreeDescriptors[] = { \
|
||||
{ &FixedSizeCompactFree, (void *)((0L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 0 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((1L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 1 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((2L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 2 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((3L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 3 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((4L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 4 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((5L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 5 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((6L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 6 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((7L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 7 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((8L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 8 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((9L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 9 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((10L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 10 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((11L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 11 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((12L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 12 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((13L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 13 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((14L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 14 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((15L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 15 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((16L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 16 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((17L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 17 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((18L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 18 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((19L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 19 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((20L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 20 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((21L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 21 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((22L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 22 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((23L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 23 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((24L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 24 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((25L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 25 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((26L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 26 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((27L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 27 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((28L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 28 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((29L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 29 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((30L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 30 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) },\
|
||||
{ &FixedSizeCompactFree, (void *)((31L << 16) | (sizeof(FixedSizeCompactAllocationChunk) + 31 * (blockSize + sizeof(MemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE))) }\
|
||||
};\
|
||||
FixedSizeCompactAllocationRoot gFixedSizeCompact##blockSize##Root = { NULL, blockSize, FixedSizeCompact##blockSize##AllocationFreeDescriptors }\
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark FIXED SIZED (FAST) ALLOCATOR DEFINITIONS
|
||||
|
||||
typedef struct FixedSizeFastMemoryBlockHeader FixedSizeFastMemoryBlockHeader;
|
||||
|
||||
struct FixedSizeFastMemoryBlockHeader {
|
||||
FixedSizeFastMemoryBlockHeader *nextFree;
|
||||
MemoryBlockHeader realHeader;
|
||||
};
|
||||
|
||||
typedef struct FixedSizeFastAllocationChunk FixedSizeFastAllocationChunk;
|
||||
|
||||
struct FixedSizeFastAllocationChunk {
|
||||
FixedSizeFastAllocationChunk *next;
|
||||
};
|
||||
|
||||
typedef struct FixedSizeFastAllocationRoot FixedSizeFastAllocationRoot;
|
||||
|
||||
struct FixedSizeFastAllocationRoot {
|
||||
FixedSizeFastAllocationChunk *firstChunk;
|
||||
FixedSizeFastMemoryBlockHeader *firstFree;
|
||||
UInt32 blockSize;
|
||||
UInt32 blocksPerChunk;
|
||||
FreeMemoryBlockDescriptor *freeDescriptor;
|
||||
};
|
||||
|
||||
void *FixedSizeFastAlloc(size_t blockSize, void *refcon);
|
||||
void FixedSizeFastFree(void *block, void *refcon);
|
||||
|
||||
#define DeclareFixedSizeFastAllocator(blockSize, blocksPerChunk) \
|
||||
extern FixedSizeFastAllocationRoot gFixedSizeFast##blockSize##Root; \
|
||||
FreeMemoryBlockDescriptor FixedSizeFast##blockSize##AllocationFreeDescriptor = { &FixedSizeFastFree, (void *)&gFixedSizeFast##blockSize##Root}; \
|
||||
FixedSizeFastAllocationRoot gFixedSizeFast##blockSize##Root = { NULL, NULL, blockSize, blocksPerChunk, &FixedSizeFast##blockSize##AllocationFreeDescriptor }
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark SMALL HEAP ALLOCATOR DEFINITIONS
|
||||
|
||||
typedef struct SmallHeapBlock SmallHeapBlock;
|
||||
|
||||
struct SmallHeapBlock {
|
||||
SmallHeapBlock *prevBlock;
|
||||
UInt32 blockSize;
|
||||
union {
|
||||
struct {
|
||||
SmallHeapBlock *nextFree;
|
||||
SmallHeapBlock *prevFree;
|
||||
} freeInfo;
|
||||
struct {
|
||||
UInt32 filler;
|
||||
MemoryBlockHeader freeProc;
|
||||
} inUseInfo;
|
||||
} info;
|
||||
};
|
||||
|
||||
enum {
|
||||
kBlockInUseFlag = 0x80000000,
|
||||
kDefaultSmallHeadMinSize = 4L,
|
||||
kDefaultSmallHeapBins = 64L,
|
||||
kMaximumBinBlockSize = kDefaultSmallHeadMinSize + 4L * kDefaultSmallHeapBins - 1,
|
||||
kSmallHeapSize = 256 * 1024
|
||||
};
|
||||
|
||||
typedef struct SmallHeapChunk SmallHeapChunk;
|
||||
|
||||
typedef struct SmallHeapRoot SmallHeapRoot;
|
||||
|
||||
struct SmallHeapRoot {
|
||||
FreeMemoryBlockDescriptor *blockFreeRoutine;
|
||||
SmallHeapChunk *firstChunk;
|
||||
SmallHeapBlock *overflow;
|
||||
SmallHeapBlock *bins[kDefaultSmallHeapBins];
|
||||
};
|
||||
|
||||
struct SmallHeapChunk {
|
||||
SmallHeapChunk *nextChunk;
|
||||
};
|
||||
|
||||
#define DeclareSmallHeapAllocator() \
|
||||
extern SmallHeapRoot gSmallHeapRoot; \
|
||||
FreeMemoryBlockDescriptor SmallHeapAllocationFreeDescriptor = { &SmallHeapFree, (void *)&gSmallHeapRoot}; \
|
||||
SmallHeapRoot gSmallHeapRoot = { &SmallHeapAllocationFreeDescriptor }
|
||||
|
||||
void *SmallHeapAlloc(size_t blockSize, void *refcon);
|
||||
void SmallHeapFree(void *address, void *refcon);
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
|
||||
// Clients must provide the following two entry points.
|
||||
|
||||
extern AllocMemoryBlockDescriptor gFastMemSmallSizeAllocators[];
|
||||
extern Ptr AllocateRawMemory(Size blockSize);
|
||||
extern void FreeRawMemory(Ptr reclaimedRawBlock);
|
||||
|
||||
// VerifyMallocHeapIntegrity will report any block headers or
|
||||
// trailers that have been overwritten.
|
||||
|
||||
extern void InstallMemoryManagerPatches();
|
||||
extern void VerifyMallocHeapIntegrity();
|
||||
static void TagReferencedBlocks();
|
||||
extern void DumpAllocHeap();
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
|
||||
#ifdef DEBUG_MAC_MEMORY
|
||||
|
||||
extern UInt32 gVerifyHeapOnEveryMalloc;
|
||||
extern UInt32 gVerifyHeapOnEveryFree;
|
||||
extern UInt32 gFillUsedBlocksWithPattern;
|
||||
extern UInt32 gFillFreeBlocksWithPattern;
|
||||
extern UInt32 gTrackLeaks;
|
||||
extern UInt32 gDontActuallyFreeMemory;
|
||||
extern SInt32 gFailToAllocateAfterNMallocs;
|
||||
|
||||
extern SInt32 gReportActiveBlocks;
|
||||
extern SInt32 gReportLeaks;
|
||||
|
||||
#endif
|
||||
|
|
@ -1,788 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <new.h> // for placement new
|
||||
|
||||
#include <MacTypes.h>
|
||||
#include <Memory.h>
|
||||
#include <Errors.h>
|
||||
#include <Processes.h>
|
||||
#include <CodeFragments.h>
|
||||
|
||||
#if __profile__
|
||||
#include <Profiler.h>
|
||||
#endif
|
||||
|
||||
#include "nsMemAllocator.h"
|
||||
|
||||
#include "nsFixedSizeAllocator.h"
|
||||
#include "nsSmallHeapAllocator.h"
|
||||
#include "nsLargeHeapAllocator.h"
|
||||
|
||||
#include "nsAllocatorManager.h"
|
||||
|
||||
/* prototypes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
pascal OSErr __initialize(const CFragInitBlock *theInitBlock);
|
||||
pascal void __terminate(void);
|
||||
|
||||
pascal OSErr __MemInitialize(const CFragInitBlock *theInitBlock);
|
||||
pascal void __MemTerminate(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsHeapZoneHeader::nsHeapZoneHeader(Ptr zonePtr, Size ptrSize)
|
||||
: mNextHeapZone(nil)
|
||||
, mZoneHandle(nil)
|
||||
, mChunkCount(0)
|
||||
, mHeapZone(nil)
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
, mSignature(kHeapZoneSignature)
|
||||
#endif
|
||||
// This ctor is used for zones in our heap, which are allocated with
|
||||
// NewPtr
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
SetupHeapZone(zonePtr, ptrSize);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsHeapZoneHeader::nsHeapZoneHeader(Handle zoneHandle, Size handleSize)
|
||||
: mNextHeapZone(nil)
|
||||
, mZoneHandle(zoneHandle)
|
||||
, mChunkCount(0)
|
||||
, mHeapZone(nil)
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
, mSignature(kHeapZoneSignature)
|
||||
#endif
|
||||
// This ctor is used for zones in temporary memory, which are allocated
|
||||
// with TempNewHandle
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
// handle should be locked here
|
||||
SetupHeapZone(*zoneHandle, handleSize);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsHeapZoneHeader::~nsHeapZoneHeader()
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
if (mZoneHandle)
|
||||
::DisposeHandle(mZoneHandle);
|
||||
else
|
||||
::DisposePtr((Ptr)this);
|
||||
|
||||
MEM_ASSERT(::MemError() == noErr, "Error on Mac memory dispose");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsHeapZoneHeader::SetupHeapZone(Ptr zonePtr, Size ptrSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
Ptr zoneStart = zonePtr + sizeof(nsHeapZoneHeader);
|
||||
Ptr endZone = zonePtr + ptrSize;
|
||||
|
||||
#if !TARGET_CARBON
|
||||
::InitZone(nil, kHeapZoneMasterPointers, endZone, zoneStart);
|
||||
#endif
|
||||
|
||||
mHeapZone = (THz)zoneStart;
|
||||
|
||||
#if !TARGET_CARBON
|
||||
// set the current zone back to the application zone, because InitZone changes it
|
||||
::SetZone(::ApplicationZone());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
Ptr nsHeapZoneHeader::AllocateZonePtr(Size ptrSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
#if !TARGET_CARBON
|
||||
::SetZone(mHeapZone);
|
||||
#endif
|
||||
Ptr thePtr = ::NewPtr(ptrSize);
|
||||
#if !TARGET_CARBON
|
||||
::SetZone(::ApplicationZone());
|
||||
#endif
|
||||
mChunkCount += (thePtr != nil);
|
||||
|
||||
return thePtr;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsHeapZoneHeader::DisposeZonePtr(Ptr thePtr, Boolean &outWasLastChunk)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
#if !TARGET_CARBON
|
||||
MEM_ASSERT(::PtrZone(thePtr) == mHeapZone, "Ptr disposed from wrong zone!");
|
||||
#endif
|
||||
::DisposePtr(thePtr);
|
||||
mChunkCount --;
|
||||
outWasLastChunk = (mChunkCount == 0);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
/* static */ nsHeapZoneHeader* nsHeapZoneHeader::GetZoneFromPtr(Ptr subheapPtr)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
#if !TARGET_CARBON
|
||||
THz ptrZone = ::PtrZone(subheapPtr);
|
||||
MEM_ASSERT(ptrZone && (::MemError() == noErr), "Problem getting zone from ptr");
|
||||
|
||||
return (nsHeapZoneHeader *)((char *)ptrZone - sizeof(nsHeapZoneHeader));
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
const SInt32 nsAllocatorManager::kNumMasterPointerBlocks = 30;
|
||||
const SInt32 nsAllocatorManager::kApplicationStackSizeIncrease = (32 * 1024);
|
||||
const float nsAllocatorManager::kHeapZoneHeapPercentage = 0.5;
|
||||
const SInt32 nsAllocatorManager::kSmallHeapByteRange = 16;
|
||||
|
||||
nsAllocatorManager* nsAllocatorManager::sAllocatorManager = nil;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsAllocatorManager::nsAllocatorManager()
|
||||
: mFixedSizeAllocators(nil)
|
||||
, mSmallBlockAllocators(nil)
|
||||
, mLargeAllocator(nil)
|
||||
, mFirstHeapZone(nil)
|
||||
, mLastHeapZone(nil)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
mMinSmallBlockSize = 165; //128; //44; // some magic numbers for now
|
||||
mMinLargeBlockSize = 261; //512; //256;
|
||||
|
||||
mNumFixedSizeAllocators = mMinSmallBlockSize / 4;
|
||||
mNumSmallBlockAllocators = 1 + (mMinLargeBlockSize - mMinSmallBlockSize) / kSmallHeapByteRange;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsAllocatorManager::~nsAllocatorManager()
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
for (SInt32 i = 0; i < mNumFixedSizeAllocators; i ++)
|
||||
{
|
||||
// because we used NewPtr and placement new, we have to destruct thus
|
||||
mFixedSizeAllocators[i]->~nsMemAllocator();
|
||||
DisposePtr((Ptr)mFixedSizeAllocators[i]);
|
||||
}
|
||||
|
||||
DisposePtr((Ptr)mFixedSizeAllocators);
|
||||
|
||||
for (SInt32 i = 0; i < mNumSmallBlockAllocators; i ++)
|
||||
{
|
||||
// because we used NewPtr and placement new, we have to destruct thus
|
||||
mSmallBlockAllocators[i]->~nsMemAllocator();
|
||||
DisposePtr((Ptr)mSmallBlockAllocators[i]);
|
||||
}
|
||||
|
||||
DisposePtr((Ptr)mSmallBlockAllocators);
|
||||
|
||||
mLargeAllocator->~nsMemAllocator();
|
||||
DisposePtr((Ptr)mLargeAllocator);
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
OSErr nsAllocatorManager::InitializeAllocators()
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
//can't use new yet!
|
||||
mFixedSizeAllocators = (nsMemAllocator **)NewPtrClear(mNumFixedSizeAllocators * sizeof(nsMemAllocator*));
|
||||
if (mFixedSizeAllocators == nil)
|
||||
return memFullErr;
|
||||
|
||||
mSmallBlockAllocators = (nsMemAllocator **)NewPtrClear(mNumSmallBlockAllocators * sizeof(nsMemAllocator*));
|
||||
if (mSmallBlockAllocators == nil)
|
||||
return memFullErr;
|
||||
|
||||
for (SInt32 i = 0; i < mNumFixedSizeAllocators; i ++)
|
||||
{
|
||||
mFixedSizeAllocators[i] = (nsMemAllocator *)NewPtr(sizeof(nsFixedSizeAllocator));
|
||||
if (mFixedSizeAllocators[i] == nil)
|
||||
return memFullErr;
|
||||
new (mFixedSizeAllocators[i]) nsFixedSizeAllocator(i * 4 + (i > 0) * 1, (i + 1) * 4);
|
||||
}
|
||||
|
||||
for (SInt32 i = 0; i < mNumSmallBlockAllocators; i ++)
|
||||
{
|
||||
mSmallBlockAllocators[i] = (nsMemAllocator *)NewPtr(sizeof(nsSmallHeapAllocator));
|
||||
if (mSmallBlockAllocators[i] == nil)
|
||||
return memFullErr;
|
||||
SInt32 minBytes = mMinSmallBlockSize + i * kSmallHeapByteRange; // lower bound of block size
|
||||
new (mSmallBlockAllocators[i]) nsSmallHeapAllocator(minBytes, minBytes + kSmallHeapByteRange - 1);
|
||||
}
|
||||
|
||||
mLargeAllocator = (nsMemAllocator *)NewPtr(sizeof(nsLargeHeapAllocator));
|
||||
if (mLargeAllocator == nil)
|
||||
return memFullErr;
|
||||
new (mLargeAllocator) nsLargeHeapAllocator(mMinLargeBlockSize, 0x7FFFFFFF);
|
||||
|
||||
// make the heap zone for our subheaps
|
||||
UInt32 heapZoneSize;
|
||||
|
||||
heapZoneSize = (UInt32)(kHeapZoneHeapPercentage * ::FreeMem());
|
||||
heapZoneSize = ( ( heapZoneSize + 3 ) & ~3 ); // round up to a multiple of 4 bytes
|
||||
|
||||
nsHeapZoneHeader *firstZone = MakeNewHeapZone(heapZoneSize, heapZoneSize);
|
||||
if (!firstZone)
|
||||
return memFullErr;
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsMemAllocator* nsAllocatorManager::GetAllocatorForBlockSize(size_t blockSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
if (blockSize < mMinSmallBlockSize)
|
||||
return mFixedSizeAllocators[ (blockSize == 0) ? 0 : ((blockSize + 3) >> 2) - 1 ];
|
||||
|
||||
if (blockSize < mMinLargeBlockSize)
|
||||
return mSmallBlockAllocators[ ((blockSize - mMinSmallBlockSize + kSmallHeapByteRange) / kSmallHeapByteRange) - 1 ];
|
||||
//return mSmallBlockAllocators[ ((blockSize + (kSmallHeapByteRange - 1)) / kSmallHeapByteRange) - mNumFixedSizeAllocators ];
|
||||
|
||||
return mLargeAllocator;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
size_t nsAllocatorManager::GetBlockSize(void *thisBlock)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
nsMemAllocator* allocator = GetAllocatorFromBlock(thisBlock);
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(allocator && allocator->IsGoodAllocator(), "Failed to get allocator for block");
|
||||
#endif
|
||||
|
||||
switch (allocator->GetAllocatorType())
|
||||
{
|
||||
case nsMemAllocator::eAllocatorTypeFixed:
|
||||
return ((nsFixedSizeAllocator*)allocator)->AllocatorGetBlockSize(thisBlock);
|
||||
|
||||
case nsMemAllocator::eAllocatorTypeSmall:
|
||||
return ((nsSmallHeapAllocator*)allocator)->AllocatorGetBlockSize(thisBlock);
|
||||
|
||||
case nsMemAllocator::eAllocatorTypeLarge:
|
||||
return ((nsLargeHeapAllocator*)allocator)->AllocatorGetBlockSize(thisBlock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsHeapZoneHeader* nsAllocatorManager::MakeNewHeapZone(Size zoneSize, Size minZoneSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
if (mFirstHeapZone == nil)
|
||||
{
|
||||
Ptr firstZonePtr = ::NewPtr(zoneSize);
|
||||
|
||||
if (!firstZonePtr) return nil;
|
||||
|
||||
mFirstHeapZone = new (firstZonePtr) nsHeapZoneHeader(firstZonePtr, zoneSize);
|
||||
mLastHeapZone = mFirstHeapZone;
|
||||
}
|
||||
else
|
||||
{
|
||||
OSErr err;
|
||||
Handle tempMemHandle = ::TempNewHandle(zoneSize, &err);
|
||||
|
||||
while (!tempMemHandle && zoneSize > minZoneSize)
|
||||
{
|
||||
zoneSize -= (128 * 1024);
|
||||
tempMemHandle = ::TempNewHandle(zoneSize, &err);
|
||||
}
|
||||
|
||||
if (!tempMemHandle) return nil;
|
||||
|
||||
// first, lock the handle hi
|
||||
HLockHi(tempMemHandle);
|
||||
|
||||
nsHeapZoneHeader *newZone = new (*tempMemHandle) nsHeapZoneHeader(tempMemHandle, zoneSize);
|
||||
mLastHeapZone->SetNextZone(newZone);
|
||||
mLastHeapZone = newZone;
|
||||
}
|
||||
|
||||
return mLastHeapZone;
|
||||
}
|
||||
|
||||
|
||||
// block size multiple. All blocks should be multiples of this size,
|
||||
// to reduce heap fragmentation
|
||||
const Size nsAllocatorManager::kChunkSizeMultiple = 2 * 1024;
|
||||
const Size nsAllocatorManager::kMaxChunkSize = 48 * 1024;
|
||||
const Size nsAllocatorManager::kMacMemoryPtrOvehead = 16; // this overhead is documented in IM:Memory 2-22
|
||||
const Size nsAllocatorManager::kTempMemHeapZoneSize = 1024 * 1024; // 1MB temp handles
|
||||
const Size nsAllocatorManager::kTempMemHeapMinZoneSize = 256 * 1024; // min 256K handle
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
Ptr nsAllocatorManager::AllocateSubheap(Size preferredSize, Size &outActualSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
nsHeapZoneHeader *thisHeapZone = mFirstHeapZone;
|
||||
|
||||
// calculate an ideal chunk size by rounding up
|
||||
preferredSize = kChunkSizeMultiple * ((preferredSize + (kChunkSizeMultiple - 1)) / kChunkSizeMultiple);
|
||||
|
||||
// take into account the memory manager's pointer overhead (16 btyes), to avoid fragmentation
|
||||
preferredSize += ((preferredSize / kChunkSizeMultiple) - 1) * kMacMemoryPtrOvehead;
|
||||
outActualSize = preferredSize;
|
||||
|
||||
while (thisHeapZone)
|
||||
{
|
||||
Ptr subheapPtr = thisHeapZone->AllocateZonePtr(preferredSize);
|
||||
if (subheapPtr)
|
||||
return subheapPtr;
|
||||
|
||||
thisHeapZone = thisHeapZone->GetNextZone();
|
||||
}
|
||||
|
||||
// we failed to allocate. Let's make a new heap zone
|
||||
UInt32 prefZoneSize = preferredSize + sizeof(nsHeapZoneHeader) + 512; // for zone overhead
|
||||
UInt32 zoneSize = (kTempMemHeapZoneSize > prefZoneSize) ? kTempMemHeapZoneSize : prefZoneSize;
|
||||
UInt32 minZoneSize = (kTempMemHeapMinZoneSize > prefZoneSize) ? kTempMemHeapMinZoneSize : prefZoneSize;
|
||||
thisHeapZone = MakeNewHeapZone(zoneSize, minZoneSize);
|
||||
if (thisHeapZone)
|
||||
return thisHeapZone->AllocateZonePtr(preferredSize);
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsAllocatorManager::FreeSubheap(Ptr subheapPtr)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
nsHeapZoneHeader *ptrHeapZone = nsHeapZoneHeader::GetZoneFromPtr(subheapPtr);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(ptrHeapZone->IsGoodZone(), "Got bad heap zone header");
|
||||
#endif
|
||||
|
||||
Boolean lastChunk;
|
||||
ptrHeapZone->DisposeZonePtr(subheapPtr, lastChunk);
|
||||
|
||||
if (lastChunk)
|
||||
{
|
||||
// remove from the list
|
||||
nsHeapZoneHeader *prevZone = nil;
|
||||
nsHeapZoneHeader *nextZone = nil;
|
||||
nsHeapZoneHeader *thisZone = mFirstHeapZone;
|
||||
|
||||
while (thisZone)
|
||||
{
|
||||
nextZone = thisZone->GetNextZone();
|
||||
|
||||
if (thisZone == ptrHeapZone)
|
||||
break;
|
||||
|
||||
prevZone = thisZone;
|
||||
thisZone = nextZone;
|
||||
}
|
||||
|
||||
if (thisZone)
|
||||
{
|
||||
if (prevZone)
|
||||
prevZone->SetNextZone(nextZone);
|
||||
|
||||
if (mFirstHeapZone == thisZone)
|
||||
mFirstHeapZone = nextZone;
|
||||
|
||||
if (mLastHeapZone == thisZone)
|
||||
mLastHeapZone = prevZone;
|
||||
}
|
||||
|
||||
// dispose it
|
||||
ptrHeapZone->~nsHeapZoneHeader(); // this disposes the ptr/handle
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
/* static */ OSErr nsAllocatorManager::InitializeMacMemory(SInt32 inNumMasterPointerBlocks,
|
||||
SInt32 inAppStackSizeInc)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
if (sAllocatorManager) return noErr;
|
||||
|
||||
// increase the stack size by 32k. Someone is bound to have fun with
|
||||
// recursion
|
||||
#if !TARGET_CARBON
|
||||
SetApplLimit(GetApplLimit() - inAppStackSizeInc);
|
||||
|
||||
MaxApplZone();
|
||||
#endif
|
||||
|
||||
for (SInt32 i = 1; i <= inNumMasterPointerBlocks; i++)
|
||||
MoreMasters();
|
||||
|
||||
// initialize our allocator object. We have to do this through NewPtr
|
||||
// and placement new, because we can't call new yet.
|
||||
OSErr err;
|
||||
Ptr allocatorManager = NewPtr(sizeof(nsAllocatorManager));
|
||||
if (!allocatorManager) return memFullErr;
|
||||
|
||||
// use placement new. The constructor can throw
|
||||
sAllocatorManager = new (allocatorManager) nsAllocatorManager;
|
||||
err = sAllocatorManager->InitializeAllocators();
|
||||
if (err != noErr)
|
||||
return err;
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
/* static */ nsAllocatorManager * nsAllocatorManager::CreateAllocatorManager()
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
if (sAllocatorManager) return sAllocatorManager;
|
||||
|
||||
if (InitializeMacMemory(kNumMasterPointerBlocks, kApplicationStackSizeIncrease) != noErr)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
::DebugStr("\pAllocator Manager initialization failed");
|
||||
#endif
|
||||
::ExitToShell();
|
||||
}
|
||||
|
||||
return sAllocatorManager;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
//--------------------------------------------------------------------
|
||||
void nsAllocatorManager::DumpMemoryStats()
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
UInt32 i;
|
||||
PRFileDesc *outFile;
|
||||
|
||||
// Enter a valid, UNIX-style full path on your system to get this
|
||||
// to work.
|
||||
outFile = PR_Open("MemoryStats.txt", PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, 0644);
|
||||
if ( outFile == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
WriteString(outFile, "\n\n--------------------------------------------------------------------------------\n");
|
||||
WriteString(outFile, "Max heap usage chart (* = 1024 bytes)\n");
|
||||
WriteString(outFile, "--------------------------------------------------------------------------------\n\n");
|
||||
|
||||
UInt32 totHeapUsed = 0;
|
||||
|
||||
for (i = 0; i < mNumFixedSizeAllocators; i ++)
|
||||
{
|
||||
mFixedSizeAllocators[i]->DumpHeapUsage(outFile);
|
||||
totHeapUsed += mFixedSizeAllocators[i]->GetMaxHeapUsage();
|
||||
}
|
||||
|
||||
for (i = 0; i < mNumSmallBlockAllocators; i ++)
|
||||
{
|
||||
mSmallBlockAllocators[i]->DumpHeapUsage(outFile);
|
||||
totHeapUsed += mSmallBlockAllocators[i]->GetMaxHeapUsage();
|
||||
}
|
||||
|
||||
char outString[256];
|
||||
sprintf(outString, "Total heap space used by allocators: %ldk\n", totHeapUsed / 1024);
|
||||
|
||||
WriteString(outFile, "--------------------------------------------------------------------------------\n");
|
||||
WriteString(outFile, outString);
|
||||
WriteString(outFile, "--------------------------------------------------------------------------------\n\n");
|
||||
|
||||
for (i = 0; i < mNumFixedSizeAllocators; i ++)
|
||||
{
|
||||
mFixedSizeAllocators[i]->DumpMemoryStats(outFile);
|
||||
}
|
||||
|
||||
for (i = 0; i < mNumSmallBlockAllocators; i ++)
|
||||
{
|
||||
mSmallBlockAllocators[i]->DumpMemoryStats(outFile);
|
||||
}
|
||||
|
||||
mLargeAllocator->DumpMemoryStats(outFile);
|
||||
|
||||
PR_Close(outFile);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void WriteString(PRFileDesc *file, const char * string)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
long len;
|
||||
long bytesWritten;
|
||||
|
||||
len = strlen ( string );
|
||||
if ( len >= 1024 ) Debugger();
|
||||
bytesWritten = PR_Write(file, string, len);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void *std::malloc(size_t blockSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
// local static copy is slightly faster
|
||||
static nsAllocatorManager* sManager;
|
||||
if (!sManager)
|
||||
sManager = nsAllocatorManager::GetAllocatorManager();
|
||||
|
||||
nsMemAllocator *allocator = sManager->GetAllocatorForBlockSize(blockSize);
|
||||
|
||||
MEM_ASSERT(allocator && allocator->IsGoodAllocator(), "This allocator ain't no good");
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
void *newBlock;
|
||||
|
||||
// we are switching here, instead of using virtual methods, for performance
|
||||
switch (allocator->GetAllocatorType())
|
||||
{
|
||||
case nsMemAllocator::eAllocatorTypeFixed:
|
||||
newBlock = ((nsFixedSizeAllocator*)allocator)->AllocatorMakeBlock(blockSize);
|
||||
break;
|
||||
|
||||
case nsMemAllocator::eAllocatorTypeSmall:
|
||||
newBlock = ((nsSmallHeapAllocator*)allocator)->AllocatorMakeBlock(blockSize);
|
||||
break;
|
||||
|
||||
case nsMemAllocator::eAllocatorTypeLarge:
|
||||
newBlock = ((nsLargeHeapAllocator*)allocator)->AllocatorMakeBlock(blockSize);
|
||||
break;
|
||||
}
|
||||
|
||||
if (newBlock)
|
||||
{
|
||||
MemoryBlockHeader *blockHeader = MemoryBlockHeader::GetHeaderFromBlock(newBlock);
|
||||
|
||||
static UInt32 sBlockID = 0;
|
||||
blockHeader->blockID = sBlockID++;
|
||||
}
|
||||
#if 0
|
||||
else
|
||||
{
|
||||
DebugStr("\pAllocation failure");
|
||||
}
|
||||
#endif
|
||||
return newBlock;
|
||||
#else
|
||||
|
||||
// we are switching here, instead of using virtual methods, for performance
|
||||
switch (allocator->GetAllocatorType())
|
||||
{
|
||||
case nsMemAllocator::eAllocatorTypeFixed:
|
||||
return ((nsFixedSizeAllocator*)allocator)->AllocatorMakeBlock(blockSize);
|
||||
|
||||
case nsMemAllocator::eAllocatorTypeSmall:
|
||||
return ((nsSmallHeapAllocator*)allocator)->AllocatorMakeBlock(blockSize);
|
||||
|
||||
case nsMemAllocator::eAllocatorTypeLarge:
|
||||
return ((nsLargeHeapAllocator*)allocator)->AllocatorMakeBlock(blockSize);
|
||||
}
|
||||
|
||||
return nil;
|
||||
|
||||
//return allocator->AllocatorMakeBlock(blockSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void std::free(void *deadBlock)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
if (!deadBlock) return;
|
||||
nsMemAllocator *allocator = nsAllocatorManager::GetAllocatorFromBlock(deadBlock);
|
||||
MEM_ASSERT(allocator && allocator->IsGoodAllocator(), "Can't get block's allocator on free. The block is hosed");
|
||||
|
||||
switch (allocator->GetAllocatorType())
|
||||
{
|
||||
case nsMemAllocator::eAllocatorTypeFixed:
|
||||
((nsFixedSizeAllocator*)allocator)->AllocatorFreeBlock(deadBlock);
|
||||
break;
|
||||
|
||||
case nsMemAllocator::eAllocatorTypeSmall:
|
||||
((nsSmallHeapAllocator*)allocator)->AllocatorFreeBlock(deadBlock);
|
||||
break;
|
||||
|
||||
case nsMemAllocator::eAllocatorTypeLarge:
|
||||
((nsLargeHeapAllocator*)allocator)->AllocatorFreeBlock(deadBlock);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void* std::realloc(void* block, size_t newSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
void *newBlock = nil;
|
||||
|
||||
if (block)
|
||||
{
|
||||
nsMemAllocator *allocator = nsAllocatorManager::GetAllocatorFromBlock(block);
|
||||
MEM_ASSERT(allocator && allocator->IsGoodAllocator(), "Can't get block's allocator on realloc. The block is hosed");
|
||||
|
||||
switch (allocator->GetAllocatorType())
|
||||
{
|
||||
case nsMemAllocator::eAllocatorTypeFixed:
|
||||
newBlock = ((nsFixedSizeAllocator*)allocator)->AllocatorResizeBlock(block, newSize);
|
||||
break;
|
||||
|
||||
case nsMemAllocator::eAllocatorTypeSmall:
|
||||
newBlock = ((nsSmallHeapAllocator*)allocator)->AllocatorResizeBlock(block, newSize);
|
||||
break;
|
||||
|
||||
case nsMemAllocator::eAllocatorTypeLarge:
|
||||
newBlock = ((nsLargeHeapAllocator*)allocator)->AllocatorResizeBlock(block, newSize);
|
||||
break;
|
||||
}
|
||||
|
||||
if (newBlock) return newBlock;
|
||||
}
|
||||
|
||||
newBlock = malloc(newSize);
|
||||
if (!newBlock) return nil;
|
||||
|
||||
if (block)
|
||||
{
|
||||
size_t oldSize = nsAllocatorManager::GetBlockSize(block);
|
||||
BlockMoveData(block, newBlock, newSize < oldSize ? newSize : oldSize);
|
||||
free(block);
|
||||
}
|
||||
return newBlock;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void *std::calloc(size_t nele, size_t elesize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
size_t space = nele * elesize;
|
||||
void *newBlock = malloc(space);
|
||||
if (newBlock)
|
||||
memset(newBlock, 0, space);
|
||||
return newBlock;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
__MemInitialize
|
||||
|
||||
Note the people can call malloc() or new() before we come here,
|
||||
so we can't rely on this being called before we do allocation.
|
||||
|
||||
----------------------------------------------------------------------------*/
|
||||
pascal OSErr __MemInitialize(const CFragInitBlock *theInitBlock)
|
||||
{
|
||||
OSErr err = __initialize(theInitBlock);
|
||||
if (err != noErr) return err;
|
||||
|
||||
#if __profile__
|
||||
if (ProfilerInit(collectDetailed, bestTimeBase, 500, 20) != noErr)
|
||||
ExitToShell();
|
||||
#endif
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
__MemTerminate
|
||||
|
||||
Code frag Terminate routine. We could do more tear-down here, but we
|
||||
cannot be sure that anyone else doesn't still need to reference
|
||||
memory that we are managing. So we can't just free all the heaps.
|
||||
We rely on the Proess Manager to free handles that we left in temp
|
||||
mem (see IM: Memory).
|
||||
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
pascal void __MemTerminate(void)
|
||||
{
|
||||
#if __profile__
|
||||
ProfilerDump("\pMemory Tester.prof");
|
||||
ProfilerTerm();
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
nsAllocatorManager::GetAllocatorManager()->DumpMemoryStats();
|
||||
#endif
|
||||
|
||||
__terminate();
|
||||
}
|
||||
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#include <MacTypes.h>
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
#include "prio.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
void WriteString(PRFileDesc *file, const char * string);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class nsHeapZoneHeader
|
||||
{
|
||||
public:
|
||||
|
||||
nsHeapZoneHeader(Ptr zonePtr, Size ptrSize);
|
||||
nsHeapZoneHeader(Handle zoneHandle, Size handleSize);
|
||||
~nsHeapZoneHeader();
|
||||
|
||||
nsHeapZoneHeader * GetNextZone() { return mNextHeapZone; }
|
||||
void SetNextZone(nsHeapZoneHeader *nextZone) { mNextHeapZone = nextZone; }
|
||||
|
||||
Ptr AllocateZonePtr(Size ptrSize);
|
||||
void DisposeZonePtr(Ptr thePtr, Boolean &outWasLastChunk);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
Boolean IsGoodZone() { return (mSignature == kHeapZoneSignature); }
|
||||
#endif
|
||||
|
||||
static nsHeapZoneHeader* GetZoneFromPtr(Ptr subheapPtr);
|
||||
|
||||
protected:
|
||||
|
||||
void SetupHeapZone(Ptr zonePtr, Size zoneSize);
|
||||
|
||||
enum
|
||||
{
|
||||
kHeapZoneMasterPointers = 24 // this number doesn't really matter, because we never
|
||||
// allocate handles in our heap zones
|
||||
};
|
||||
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
enum {
|
||||
kHeapZoneSignature = 'HZne'
|
||||
};
|
||||
|
||||
OSType mSignature;
|
||||
#endif
|
||||
|
||||
nsHeapZoneHeader *mNextHeapZone;
|
||||
Handle mZoneHandle; // the handle containing the zone. Nil if Ptr in app heap
|
||||
UInt32 mChunkCount; // how many chunks are allocated in this zone
|
||||
THz mHeapZone;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class nsAllocatorManager
|
||||
{
|
||||
public:
|
||||
|
||||
static const SInt32 kNumMasterPointerBlocks;
|
||||
static const SInt32 kApplicationStackSizeIncrease;
|
||||
|
||||
static const float kHeapZoneHeapPercentage;
|
||||
static const SInt32 kTempMemHeapZoneSize;
|
||||
static const SInt32 kTempMemHeapMinZoneSize;
|
||||
|
||||
static const Size kChunkSizeMultiple;
|
||||
static const Size kMaxChunkSize;
|
||||
|
||||
static const SInt32 kSmallHeapByteRange;
|
||||
|
||||
static nsAllocatorManager* GetAllocatorManager() { return sAllocatorManager ? sAllocatorManager : CreateAllocatorManager(); }
|
||||
|
||||
nsAllocatorManager();
|
||||
~nsAllocatorManager();
|
||||
|
||||
OSErr InitializeAllocators();
|
||||
|
||||
static OSErr InitializeMacMemory(SInt32 inNumMasterPointerBlocks,
|
||||
SInt32 inAppStackSizeInc);
|
||||
|
||||
inline nsMemAllocator* GetAllocatorForBlockSize(size_t blockSize);
|
||||
|
||||
static nsMemAllocator* GetAllocatorFromBlock(void *thisBlock)
|
||||
{
|
||||
MemoryBlockHeader *blockHeader = MemoryBlockHeader::GetHeaderFromBlock(thisBlock);
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(blockHeader->HasHeaderTag(kUsedBlockHeaderTag), "Bad block header tag");
|
||||
MEM_ASSERT(blockHeader->owningChunk->IsGoodChunk(), "Block has bad chunk pointer");
|
||||
#endif
|
||||
return (blockHeader->owningChunk->GetOwningAllocator());
|
||||
}
|
||||
|
||||
|
||||
static size_t GetBlockSize(void *thisBlock);
|
||||
|
||||
|
||||
Ptr AllocateSubheap(Size preferredSize, Size &outActualSize);
|
||||
void FreeSubheap(Ptr subheapPtr);
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
void DumpMemoryStats();
|
||||
#endif
|
||||
|
||||
static nsAllocatorManager* CreateAllocatorManager();
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
static const Size kMacMemoryPtrOvehead;
|
||||
|
||||
nsHeapZoneHeader * MakeNewHeapZone(Size zoneSize, Size minZoneSize);
|
||||
|
||||
private:
|
||||
|
||||
SInt32 mNumFixedSizeAllocators;
|
||||
SInt32 mNumSmallBlockAllocators;
|
||||
|
||||
UInt32 mMinSmallBlockSize; // blocks >= this size come out of the small block allocator
|
||||
UInt32 mMinLargeBlockSize; // blocks >= this size come out of the large allocator
|
||||
|
||||
nsMemAllocator** mFixedSizeAllocators; // array of pointers to allocator objects
|
||||
nsMemAllocator** mSmallBlockAllocators; // array of pointers to allocator objects
|
||||
|
||||
nsMemAllocator* mLargeAllocator;
|
||||
|
||||
nsHeapZoneHeader* mFirstHeapZone; // first of a linked list of heap zones
|
||||
nsHeapZoneHeader* mLastHeapZone; // last of a linked list of heap zones
|
||||
|
||||
THz mHeapZone; // the heap zone for our memory heaps
|
||||
|
||||
static nsAllocatorManager *sAllocatorManager;
|
||||
|
||||
};
|
||||
|
|
@ -1,279 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#include <new.h> // for placement new
|
||||
#include <MacMemory.h>
|
||||
|
||||
#include "nsMemAllocator.h"
|
||||
#include "nsAllocatorManager.h"
|
||||
#include "nsFixedSizeAllocator.h"
|
||||
|
||||
const UInt32 FixedMemoryBlock::kFixedSizeBlockOverhead = sizeof(FixedMemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsFixedSizeAllocator::nsFixedSizeAllocator(size_t minBlockSize, size_t maxBlockSize)
|
||||
: nsMemAllocator(eAllocatorTypeFixed, minBlockSize, maxBlockSize)
|
||||
, mChunkWithSpace(nil)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
mBaseChunkSize = mTempChunkSize = (nsAllocatorManager::kChunkSizeMultiple);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsFixedSizeAllocator::~nsFixedSizeAllocator()
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsHeapChunk* nsFixedSizeAllocator::FindChunkWithSpace(size_t blockSize) const
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
if (mChunkWithSpace && mChunkWithSpace->GetFreeList())
|
||||
return mChunkWithSpace;
|
||||
|
||||
nsFixedSizeHeapChunk* chunk = (nsFixedSizeHeapChunk *)mFirstChunk;
|
||||
|
||||
// Try to find an existing chunk with a free block.
|
||||
while (chunk != nil)
|
||||
{
|
||||
if (chunk->GetFreeList() != nil)
|
||||
return chunk;
|
||||
|
||||
chunk = (nsFixedSizeHeapChunk *)chunk->GetNextChunk();
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void *nsFixedSizeAllocator::AllocatorMakeBlock(size_t blockSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
nsFixedSizeHeapChunk* chunk = (nsFixedSizeHeapChunk *)FindChunkWithSpace(blockSize);
|
||||
|
||||
if (chunk == nil)
|
||||
{
|
||||
chunk = (nsFixedSizeHeapChunk *)AllocateChunk(blockSize);
|
||||
if (!chunk) return nil;
|
||||
|
||||
mChunkWithSpace = chunk;
|
||||
}
|
||||
|
||||
FixedMemoryBlock* blockHeader = chunk->FetchFirstFree();
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
blockHeader->SetHeaderTag(kUsedBlockHeaderTag);
|
||||
blockHeader->SetTrailerTag(GetAllocatorBlockSize(), kUsedBlockTrailerTag);
|
||||
|
||||
blockHeader->ZapBlockContents(blockSize, kUsedMemoryFillPattern);
|
||||
|
||||
UInt32 paddedSize = (blockSize + 3) & ~3;
|
||||
blockHeader->SetPaddingBytes(paddedSize - blockSize);
|
||||
blockHeader->FillPaddingBytes(mMaxBlockSize);
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
blockHeader->blockHeader.header.logicalBlockSize = blockSize;
|
||||
AccountForNewBlock(blockSize);
|
||||
#endif
|
||||
|
||||
return (void *)&blockHeader->memory;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsFixedSizeAllocator::AllocatorFreeBlock(void *freeBlock)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
FixedMemoryBlock* blockHeader = FixedMemoryBlock::GetBlockHeader(freeBlock);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(blockHeader->HasHeaderTag(kUsedBlockHeaderTag), "Bad block header");
|
||||
MEM_ASSERT(blockHeader->GetTrailerTag(GetAllocatorBlockSize()) == kUsedBlockTrailerTag, "Bad block trailer");
|
||||
MEM_ASSERT(blockHeader->CheckPaddingBytes(GetAllocatorBlockSize()), "Block bounds have been overwritten");
|
||||
|
||||
blockHeader->ZapBlockContents(GetAllocatorBlockSize(), kFreeMemoryFillPattern);
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
AccountForFreedBlock(blockHeader->blockHeader.header.logicalBlockSize);
|
||||
#endif
|
||||
|
||||
nsFixedSizeHeapChunk* chunk = blockHeader->GetOwningChunk();
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
blockHeader->SetHeaderTag(kFreeBlockHeaderTag);
|
||||
blockHeader->SetTrailerTag(GetAllocatorBlockSize(), kFreeBlockTrailerTag);
|
||||
#endif
|
||||
|
||||
chunk->ReturnToFreeList(blockHeader);
|
||||
|
||||
// if this chunk is completely empty and it's not the first chunk then free it
|
||||
if ( chunk->IsEmpty() && chunk != mFirstChunk )
|
||||
{
|
||||
if (chunk == mChunkWithSpace)
|
||||
mChunkWithSpace = nil;
|
||||
|
||||
FreeChunk(chunk);
|
||||
}
|
||||
else
|
||||
{
|
||||
mChunkWithSpace = chunk; // we know is has some space now
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void *nsFixedSizeAllocator::AllocatorResizeBlock(void *block, size_t newSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
// let blocks shrink to at most 16 bytes below this allocator's block size
|
||||
if (newSize > mMaxBlockSize || newSize <= mMaxBlockSize - kMaxBlockResizeSlop)
|
||||
return nil;
|
||||
|
||||
FixedMemoryBlock* blockHeader = FixedMemoryBlock::GetBlockHeader(block);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(blockHeader->HasHeaderTag(kUsedBlockHeaderTag), "Bad block header");
|
||||
MEM_ASSERT(blockHeader->GetTrailerTag(GetAllocatorBlockSize()) == kUsedBlockTrailerTag, "Bad block trailer");
|
||||
MEM_ASSERT(blockHeader->CheckPaddingBytes(mMaxBlockSize), "Block bounds have been overwritten");
|
||||
|
||||
// if we shrunk the block to below this allocator's normal size range, then these
|
||||
// padding bytes won't be any use. But they are tested using mBlockSize, so we
|
||||
// have to udpate them anyway.
|
||||
UInt32 paddedSize = (newSize + 3) & ~3;
|
||||
blockHeader->SetPaddingBytes(paddedSize - newSize);
|
||||
blockHeader->FillPaddingBytes(mMaxBlockSize);
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
AccountForResizedBlock(blockHeader->blockHeader.header.logicalBlockSize, newSize);
|
||||
blockHeader->blockHeader.header.logicalBlockSize = newSize;
|
||||
#endif
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
size_t nsFixedSizeAllocator::AllocatorGetBlockSize(void *thisBlock)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
return mMaxBlockSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsHeapChunk *nsFixedSizeAllocator::AllocateChunk(size_t requestedBlockSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
Size actualChunkSize;
|
||||
|
||||
// adapt the chunk size if we have already allocated a number of chunks, and it's not above a max size
|
||||
if (mNumChunks > 4 && mBaseChunkSize < nsAllocatorManager::kMaxChunkSize)
|
||||
mBaseChunkSize *= 2;
|
||||
|
||||
Ptr chunkMemory = nsAllocatorManager::GetAllocatorManager()->AllocateSubheap(mBaseChunkSize, actualChunkSize);
|
||||
if (!chunkMemory) return nil;
|
||||
|
||||
// use placement new to initialize the chunk in the memory block
|
||||
nsHeapChunk *newHeapChunk = new (chunkMemory) nsFixedSizeHeapChunk(this, actualChunkSize);
|
||||
if (newHeapChunk)
|
||||
AddToChunkList(newHeapChunk);
|
||||
|
||||
return newHeapChunk;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsFixedSizeAllocator::FreeChunk(nsHeapChunk *chunkToFree)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
RemoveFromChunkList(chunkToFree);
|
||||
// we used placement new to make it, so we have to delete like this
|
||||
nsFixedSizeHeapChunk *thisChunk = (nsFixedSizeHeapChunk *)chunkToFree;
|
||||
thisChunk->~nsFixedSizeHeapChunk();
|
||||
|
||||
nsAllocatorManager::GetAllocatorManager()->FreeSubheap((Ptr)thisChunk);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsFixedSizeHeapChunk::nsFixedSizeHeapChunk(
|
||||
nsMemAllocator *inOwningAllocator,
|
||||
Size heapSize) :
|
||||
nsHeapChunk(inOwningAllocator, heapSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
nsFixedSizeAllocator *allocator = (nsFixedSizeAllocator *)mOwningAllocator;
|
||||
UInt32 blockSize = allocator->GetAllocatorBlockSize();
|
||||
UInt32 allocBlockSize = blockSize + FixedMemoryBlock::kFixedSizeBlockOverhead;
|
||||
|
||||
// work out how much we can actually store in the heap
|
||||
UInt32 numBlocks = (heapSize - sizeof(nsFixedSizeHeapChunk)) / allocBlockSize;
|
||||
mHeapSize = numBlocks * allocBlockSize;
|
||||
|
||||
// build the free list for this chunk
|
||||
UInt32 blockCount = numBlocks - 1; // -1 because we do the last one by hand
|
||||
|
||||
FixedMemoryBlock *freePtr = mMemory;
|
||||
FixedMemoryBlock *nextFree;
|
||||
|
||||
mFreeList = freePtr;
|
||||
|
||||
do
|
||||
{
|
||||
nextFree = (FixedMemoryBlock *) ((UInt32)freePtr + allocBlockSize);
|
||||
freePtr->SetOwningChunk(this);
|
||||
freePtr->SetNextFree(nextFree);
|
||||
|
||||
freePtr = nextFree;
|
||||
}
|
||||
while (--blockCount);
|
||||
|
||||
freePtr->SetOwningChunk(this);
|
||||
freePtr->SetNextFree(nil);
|
||||
|
||||
}
|
||||
|
|
@ -1,218 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
class nsMemAllocator;
|
||||
class nsFixedSizeHeapChunk;
|
||||
|
||||
|
||||
struct FixedMemoryBlockHeader
|
||||
{
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
UInt16 blockFlags; // unused at present
|
||||
UInt16 blockPadding;
|
||||
#endif
|
||||
|
||||
MemoryBlockHeader header; // this must be the last variable before memory
|
||||
};
|
||||
|
||||
|
||||
struct FixedMemoryBlock
|
||||
{
|
||||
static FixedMemoryBlock* GetBlockHeader(void *block)
|
||||
{ return (FixedMemoryBlock *)((char *)block - sizeof(FixedMemoryBlockHeader)); }
|
||||
|
||||
FixedMemoryBlock* GetNextFree()
|
||||
{ return next; }
|
||||
void SetNextFree(FixedMemoryBlock *nextFree)
|
||||
{ next = nextFree; }
|
||||
|
||||
void SetOwningChunk(nsHeapChunk *inOwningChunk)
|
||||
{ blockHeader.header.owningChunk = inOwningChunk; }
|
||||
|
||||
nsFixedSizeHeapChunk* GetOwningChunk()
|
||||
{ return (nsFixedSizeHeapChunk *)blockHeader.header.owningChunk; }
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
enum {
|
||||
kBlockPaddingBytes = 'ðððð'
|
||||
};
|
||||
|
||||
void SetPaddingBytes(UInt32 padding) { blockHeader.blockPadding = padding; }
|
||||
void FillPaddingBytes(UInt32 blockSize) {
|
||||
long *lastLong = (long *)((char *)&memory + blockSize - sizeof(long));
|
||||
UInt32 mask = (1 << (8 * blockHeader.blockPadding)) - 1;
|
||||
*lastLong &= ~mask;
|
||||
*lastLong |= (mask & kBlockPaddingBytes);
|
||||
}
|
||||
|
||||
Boolean CheckPaddingBytes(UInt32 blockSize) {
|
||||
long *lastLong = (long *)((char *)&memory + blockSize - sizeof(long));
|
||||
UInt32 mask = (1 << (8 * blockHeader.blockPadding)) - 1;
|
||||
return (*lastLong & mask) == (mask & kBlockPaddingBytes);
|
||||
}
|
||||
UInt32 GetPaddingBytes() { return blockHeader.blockPadding; }
|
||||
|
||||
void ZapBlockContents(UInt32 blockSize, UInt8 pattern)
|
||||
{
|
||||
memset(&memory, pattern, blockSize);
|
||||
}
|
||||
|
||||
|
||||
// inline, so won't crash if this is a bad block
|
||||
Boolean HasHeaderTag(MemoryBlockTag inHeaderTag)
|
||||
{ return blockHeader.header.headerTag == inHeaderTag; }
|
||||
void SetHeaderTag(MemoryBlockTag inHeaderTag)
|
||||
{ blockHeader.header.headerTag = inHeaderTag; }
|
||||
|
||||
void SetTrailerTag(UInt32 blockSize, MemoryBlockTag theTag)
|
||||
{
|
||||
MemoryBlockTrailer *trailer = (MemoryBlockTrailer *)((char *)&memory + blockSize);
|
||||
trailer->trailerTag = theTag;
|
||||
}
|
||||
MemoryBlockTag GetTrailerTag(UInt32 blockSize)
|
||||
{
|
||||
MemoryBlockTrailer *trailer = (MemoryBlockTrailer *)((char *)&memory + blockSize);
|
||||
return trailer->trailerTag;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const UInt32 kFixedSizeBlockOverhead;
|
||||
|
||||
FixedMemoryBlockHeader blockHeader;
|
||||
|
||||
union {
|
||||
FixedMemoryBlock* next;
|
||||
void* memory;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
class nsFixedSizeHeapChunk : public nsHeapChunk
|
||||
{
|
||||
public:
|
||||
|
||||
nsFixedSizeHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize);
|
||||
~nsFixedSizeHeapChunk() {}
|
||||
|
||||
FixedMemoryBlock* GetFreeList() const { return mFreeList; }
|
||||
void SetFreeList(FixedMemoryBlock *nextFree) { mFreeList = nextFree; }
|
||||
|
||||
FixedMemoryBlock* FetchFirstFree()
|
||||
{
|
||||
FixedMemoryBlock* firstFree = mFreeList;
|
||||
mFreeList = firstFree->GetNextFree();
|
||||
mUsedBlocks ++;
|
||||
return firstFree;
|
||||
}
|
||||
|
||||
void ReturnToFreeList(FixedMemoryBlock *freeBlock)
|
||||
{
|
||||
freeBlock->SetNextFree(mFreeList);
|
||||
mFreeList = freeBlock;
|
||||
mUsedBlocks --;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
UInt32 chunkSize;
|
||||
UInt32 numBlocks;
|
||||
#endif
|
||||
|
||||
FixedMemoryBlock *mFreeList;
|
||||
FixedMemoryBlock mMemory[];
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class nsFixedSizeAllocator : public nsMemAllocator
|
||||
{
|
||||
private:
|
||||
|
||||
typedef nsMemAllocator Inherited;
|
||||
|
||||
public:
|
||||
|
||||
nsFixedSizeAllocator(size_t minBlockSize, size_t maxBlockSize);
|
||||
~nsFixedSizeAllocator();
|
||||
|
||||
void * AllocatorMakeBlock(size_t blockSize);
|
||||
void AllocatorFreeBlock(void *freeBlock);
|
||||
void * AllocatorResizeBlock(void *block, size_t newSize);
|
||||
size_t AllocatorGetBlockSize(void *thisBlock);
|
||||
|
||||
nsHeapChunk* AllocateChunk(size_t requestedBlockSize);
|
||||
void FreeChunk(nsHeapChunk *chunkToFree);
|
||||
|
||||
inline nsHeapChunk* FindChunkWithSpace(size_t blockSize) const;
|
||||
|
||||
UInt32 GetAllocatorBlockSize() { return mMaxBlockSize; }
|
||||
|
||||
protected:
|
||||
|
||||
enum {
|
||||
kMaxBlockResizeSlop = 16
|
||||
};
|
||||
|
||||
nsFixedSizeHeapChunk *mChunkWithSpace; // cheap optimization
|
||||
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
UInt32 mChunksAllocated;
|
||||
UInt32 mMaxChunksAllocated;
|
||||
|
||||
UInt32 mTotalChunkSize;
|
||||
UInt32 mMaxTotalChunkSize;
|
||||
|
||||
UInt32 mBlocksAllocated;
|
||||
UInt32 mMaxBlocksAllocated;
|
||||
|
||||
UInt32 mBlocksUsed;
|
||||
UInt32 mMaxBlocksUsed;
|
||||
|
||||
UInt32 mBlockSpaceUsed;
|
||||
UInt32 mMaxBlockSpaceUsed;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define GC_DEBUG
|
||||
#include "gc.h"
|
||||
|
||||
// GC implementation of malloc/free, for testing purposes
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void *malloc(size_t blockSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
#ifdef GC_DEBUG
|
||||
return GC_MALLOC(blockSize);
|
||||
#else
|
||||
if (blockSize <= 10000)
|
||||
return GC_MALLOC(blockSize);
|
||||
else
|
||||
return GC_malloc_ignore_off_page(blockSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void free(void *deadBlock)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
if (deadBlock != NULL)
|
||||
GC_FREE(deadBlock);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void* realloc(void* block, size_t newSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
#ifdef GC_DEBUG
|
||||
return GC_REALLOC(block, newSize);
|
||||
#else
|
||||
size_t oldSize = GC_size(block);
|
||||
void * newBlock = block;
|
||||
|
||||
if (newSize <= 10000)
|
||||
return(GC_REALLOC(block, newSize));
|
||||
|
||||
if (newSize <= oldSize)
|
||||
return(block);
|
||||
|
||||
newBlock = GC_malloc_ignore_off_page(newSize);
|
||||
if (newBlock == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy(newBlock, block, oldSize);
|
||||
GC_FREE(block);
|
||||
|
||||
return(newBlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void *calloc(size_t nele, size_t elesize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
// GC_MALLOC returns cleared blocks for us.
|
||||
size_t space = nele * elesize;
|
||||
return GC_MALLOC(space);
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <Files.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "gc.h"
|
||||
#include "gc_fragments.h"
|
||||
#include "generic_threads.h"
|
||||
|
||||
#ifndef GC_LEAK_DETECTOR
|
||||
|
||||
void MWUnmangle(const char *mangled_name, char *unmangled_name, size_t buffersize);
|
||||
|
||||
// stub implementations, when GC leak detection isn't on. these are needed so that
|
||||
// NSStdLib has something to export for these functions, even when the GC isn't used.
|
||||
void GC_register_fragment(char* dataStart, char* dataEnd,
|
||||
char* codeStart, char* codeEnd,
|
||||
const FSSpec* fragmentSpec) {}
|
||||
void GC_unregister_fragment(char* dataStart, char* dataEnd,
|
||||
char* codeStart, char* codeEnd) {}
|
||||
void GC_clear_roots() {}
|
||||
void GC_generic_init_threads() {}
|
||||
void GC_gcollect() {}
|
||||
|
||||
FILE* GC_stdout = NULL;
|
||||
FILE* GC_stderr = NULL;
|
||||
|
||||
int GC_address_to_source(char* codeAddr, char symbolName[256], char fileName[256], UInt32* fileOffset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
GC_PTR GC_malloc_atomic(size_t size_in_bytes) { return NULL; }
|
||||
|
||||
void MWUnmangle(const char *mangled_name, char *unmangled_name, size_t buffersize)
|
||||
{
|
||||
strncpy(unmangled_name, mangled_name, buffersize);
|
||||
}
|
||||
|
||||
// TODO: move these to gc.h.
|
||||
void GC_mark_object(GC_PTR object, GC_word mark);
|
||||
void GC_trace_object(GC_PTR object, int verbose);
|
||||
|
||||
void GC_mark_object(GC_PTR object, GC_word mark) {}
|
||||
void GC_trace_object(GC_PTR object, int verbose) {}
|
||||
|
||||
#endif
|
|
@ -1,544 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <new.h> // for placement new
|
||||
#include <MacMemory.h>
|
||||
|
||||
#include "nsMemAllocator.h"
|
||||
#include "nsAllocatorManager.h"
|
||||
#include "nsLargeHeapAllocator.h"
|
||||
|
||||
|
||||
const UInt32 LargeBlockHeader::kLargeBlockOverhead = sizeof(LargeBlockHeader) + MEMORY_BLOCK_TAILER_SIZE;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsLargeHeapAllocator::nsLargeHeapAllocator(size_t minBlockSize, size_t maxBlockSize)
|
||||
: nsMemAllocator(eAllocatorTypeLarge, minBlockSize, maxBlockSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
mBaseChunkSize = mTempChunkSize = (64 * 1024);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsLargeHeapAllocator::~nsLargeHeapAllocator()
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void * nsLargeHeapAllocator::AllocatorMakeBlock(size_t blockSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
nsLargeHeapChunk* chunk = (nsLargeHeapChunk *)mFirstChunk;
|
||||
LargeBlockHeader *theBlock = nil;
|
||||
|
||||
UInt32 allocSize = GetPaddedBlockSize(blockSize);
|
||||
|
||||
// walk through all of our chunks, trying to allocate memory from somewhere
|
||||
while (chunk)
|
||||
{
|
||||
if (chunk->GetLargestFreeBlock() >= allocSize)
|
||||
{
|
||||
theBlock = chunk->GetSpaceForBlock(blockSize);
|
||||
if (theBlock)
|
||||
break;
|
||||
}
|
||||
|
||||
chunk = (nsLargeHeapChunk *)chunk->GetNextChunk();
|
||||
}
|
||||
|
||||
if (!theBlock)
|
||||
{
|
||||
chunk = (nsLargeHeapChunk *)AllocateChunk(blockSize);
|
||||
if (!chunk) return nil;
|
||||
|
||||
theBlock = chunk->GetSpaceForBlock(blockSize);
|
||||
}
|
||||
|
||||
if (theBlock)
|
||||
{
|
||||
theBlock->SetLogicalSize(blockSize);
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
theBlock->header.logicalBlockSize = blockSize; // yes, it is stored in 2 places in this allocator
|
||||
AccountForNewBlock(blockSize);
|
||||
#endif
|
||||
|
||||
return &(theBlock->memory);
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void *nsLargeHeapAllocator::AllocatorResizeBlock(void *block, size_t newSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
LargeBlockHeader *blockHeader = LargeBlockHeader::GetBlockHeader(block);
|
||||
nsLargeHeapChunk *chunk = blockHeader->GetOwningChunk();
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(blockHeader->HasHeaderTag(kUsedBlockHeaderTag), "Bad block header on realloc");
|
||||
MEM_ASSERT(blockHeader->HasTrailerTag(blockHeader->GetBlockSize(), kUsedBlockTrailerTag), "Bad block trailer on realloc");
|
||||
MEM_ASSERT(blockHeader->CheckPaddingBytes(), "Block has overwritten its bounds");
|
||||
#endif
|
||||
|
||||
UInt32 newAllocSize = (newSize + 3) & ~3;
|
||||
|
||||
// we can resize this block to any size, provided it fits.
|
||||
|
||||
if (newAllocSize < blockHeader->GetBlockSize()) // shrinking
|
||||
{
|
||||
return chunk->ShrinkBlock(blockHeader, newSize);
|
||||
}
|
||||
else if (newAllocSize > blockHeader->GetBlockSize()) // growing
|
||||
{
|
||||
return chunk->GrowBlock(blockHeader, newSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
return chunk->ResizeBlockInPlace(blockHeader, newSize);
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsLargeHeapAllocator::AllocatorFreeBlock(void *freeBlock)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
LargeBlockHeader *blockHeader = LargeBlockHeader::GetBlockHeader(freeBlock);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(blockHeader->HasHeaderTag(kUsedBlockHeaderTag), "Bad block header on free");
|
||||
MEM_ASSERT(blockHeader->HasTrailerTag(blockHeader->GetBlockSize(), kUsedBlockTrailerTag), "Bad block trailer on free");
|
||||
MEM_ASSERT(blockHeader->CheckPaddingBytes(), "Block overwrote bounds");
|
||||
|
||||
blockHeader->ZapBlockContents(kFreeMemoryFillPattern);
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
AccountForFreedBlock(blockHeader->header.logicalBlockSize);
|
||||
#endif
|
||||
|
||||
nsLargeHeapChunk *chunk = blockHeader->GetOwningChunk();
|
||||
chunk->ReturnBlock(blockHeader);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
blockHeader->SetHeaderTag(kFreeBlockHeaderTag);
|
||||
#endif
|
||||
|
||||
// if this chunk is completely empty and it's not the first chunk then free it
|
||||
if (chunk->IsEmpty() && chunk != mFirstChunk)
|
||||
FreeChunk(chunk);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
size_t nsLargeHeapAllocator::AllocatorGetBlockSize(void *thisBlock)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
LargeBlockHeader* blockHeader = (LargeBlockHeader *)((char *)thisBlock - sizeof(LargeBlockHeader));
|
||||
|
||||
return blockHeader->GetLogicalSize();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsHeapChunk *nsLargeHeapAllocator::AllocateChunk(size_t requestedBlockSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
Size chunkSize = mBaseChunkSize, actualChunkSize;
|
||||
|
||||
size_t paddedBlockSize = (( requestedBlockSize + 3 ) & ~3) + 3 * LargeBlockHeader::kLargeBlockOverhead + sizeof(nsLargeHeapChunk);
|
||||
|
||||
if (paddedBlockSize > chunkSize)
|
||||
chunkSize = paddedBlockSize;
|
||||
|
||||
Ptr chunkMemory = nsAllocatorManager::GetAllocatorManager()->AllocateSubheap(chunkSize, actualChunkSize);
|
||||
if (!chunkMemory) return nil;
|
||||
|
||||
// use placement new to initialize the chunk in the memory block
|
||||
nsHeapChunk *newHeapChunk = new (chunkMemory) nsLargeHeapChunk(this, actualChunkSize);
|
||||
|
||||
if (newHeapChunk)
|
||||
AddToChunkList(newHeapChunk);
|
||||
|
||||
return newHeapChunk;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsLargeHeapAllocator::FreeChunk(nsHeapChunk *chunkToFree)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
RemoveFromChunkList(chunkToFree);
|
||||
// we used placement new to make it, so we have to delete like this
|
||||
nsLargeHeapChunk *thisChunk = (nsLargeHeapChunk *)chunkToFree;
|
||||
thisChunk->~nsLargeHeapChunk();
|
||||
|
||||
nsAllocatorManager::GetAllocatorManager()->FreeSubheap((Ptr)thisChunk);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsLargeHeapChunk::nsLargeHeapChunk(
|
||||
nsMemAllocator *inOwningAllocator,
|
||||
Size heapSize) :
|
||||
nsHeapChunk(inOwningAllocator, heapSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
heapSize -= sizeof(nsLargeHeapChunk); // subtract heap overhead
|
||||
|
||||
// mark how much we can actually store in the heap
|
||||
mHeapSize = heapSize - 3 * sizeof(LargeBlockHeader);
|
||||
|
||||
// the head block is zero size and is never free
|
||||
mHead->SetPrevBlock((LargeBlockHeader *) -1L);
|
||||
|
||||
// we have a free block in the middle
|
||||
LargeBlockHeader *freeBlock = mHead->SkipDummyBlock();
|
||||
|
||||
mHead->SetNextBlock(freeBlock);
|
||||
mHead->SetLogicalSize(0);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
mHead->SetPaddingBytes(0);
|
||||
|
||||
mHead->SetHeaderTag(kDummyBlockHeaderTag);
|
||||
mHead->header.blockID = -1;
|
||||
#endif
|
||||
|
||||
freeBlock->SetPrevBlock(nil);
|
||||
freeBlock->SetNextBlock( (LargeBlockHeader *) ( (UInt32)freeBlock + heapSize - 2 * LargeBlockHeader::kLargeBlockOverhead) );
|
||||
|
||||
// and then a zero sized allocated block at the end
|
||||
mTail = freeBlock->GetNextBlock();
|
||||
mTail->SetNextBlock(nil);
|
||||
mTail->SetPrevBlock(freeBlock);
|
||||
|
||||
mTotalFree = mLargestFreeBlock = freeBlock->GetBlockHeapUsageSize();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsLargeHeapChunk::~nsLargeHeapChunk()
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
LargeBlockHeader* nsLargeHeapChunk::GetSpaceForBlock(UInt32 blockSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
UInt32 allocSize = ((blockSize + 3) & ~3) + LargeBlockHeader::kLargeBlockOverhead;
|
||||
|
||||
if (allocSize > mLargestFreeBlock) return nil;
|
||||
//Boolean expectFailure = (allocSize > mTotalFree);
|
||||
|
||||
/* scan through the blocks in this chunk looking for a big enough free block */
|
||||
/* we never allocate the head block */
|
||||
LargeBlockHeader *prevBlock = GetHeadBlock();
|
||||
LargeBlockHeader *blockHeader = prevBlock->GetNextBlock();
|
||||
|
||||
do
|
||||
{
|
||||
if (blockHeader->IsFreeBlock())
|
||||
{
|
||||
UInt32 freeBlockSize = blockHeader->GetBlockHeapUsageSize();
|
||||
if (freeBlockSize >= allocSize)
|
||||
break;
|
||||
}
|
||||
|
||||
prevBlock = blockHeader;
|
||||
blockHeader = blockHeader->GetNextBlock();
|
||||
}
|
||||
while (blockHeader);
|
||||
|
||||
// if we failed to find a block, return nil
|
||||
if (!blockHeader)
|
||||
return nil;
|
||||
|
||||
// is there space at the end of this block for a free block?
|
||||
if ( ( blockHeader->GetBlockHeapUsageSize() - allocSize ) > LargeBlockHeader::kLargeBlockOverhead )
|
||||
{
|
||||
LargeBlockHeader *freeBlock = (LargeBlockHeader *) ( (char *) blockHeader + allocSize );
|
||||
freeBlock->SetPrevBlock(nil);
|
||||
freeBlock->SetNextBlock(blockHeader->GetNextBlock());
|
||||
freeBlock->GetNextBlock()->SetPrevBlock(freeBlock);
|
||||
blockHeader->SetNextBlock(freeBlock);
|
||||
}
|
||||
|
||||
// allocate this block
|
||||
blockHeader->SetPrevBlock(prevBlock);
|
||||
blockHeader->SetOwningChunk(this);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
blockHeader->SetHeaderTag(kUsedBlockHeaderTag);
|
||||
blockHeader->SetTrailerTag(blockHeader->GetBlockSize(), kUsedBlockTrailerTag);
|
||||
blockHeader->SetPaddingBytes(((blockSize + 3) & ~3) - blockSize);
|
||||
blockHeader->ZapBlockContents(kUsedMemoryFillPattern);
|
||||
blockHeader->FillPaddingBytes();
|
||||
#endif
|
||||
|
||||
mTotalFree -= blockHeader->GetBlockHeapUsageSize();
|
||||
IncrementUsedBlocks();
|
||||
|
||||
UpdateLargestFreeBlock(); // we could optimize this
|
||||
|
||||
//MEM_ASSERT(!expectFailure, "I though this would fail!");
|
||||
return blockHeader;
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void *nsLargeHeapChunk::GrowBlock(LargeBlockHeader *growBlock, size_t newSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
LargeBlockHeader* freeBlock = growBlock->GetNextBlock();
|
||||
|
||||
// is the block following this block a free block?
|
||||
if (!freeBlock->IsFreeBlock())
|
||||
return nil;
|
||||
|
||||
// round the block size up to a multiple of four and add space for the header and trailer
|
||||
UInt32 newAllocSize = ( ( newSize + 3 ) & ~3 ) + LargeBlockHeader::kLargeBlockOverhead;
|
||||
UInt32 oldAllocSize = growBlock->GetBlockHeapUsageSize();
|
||||
|
||||
/* is it big enough? */
|
||||
UInt32 freeBlockSize = freeBlock->GetBlockHeapUsageSize();
|
||||
if (freeBlockSize + oldAllocSize < newAllocSize)
|
||||
return nil;
|
||||
|
||||
// grow this block
|
||||
#if STATS_MAC_MEMORY
|
||||
UInt32 oldLogicalSize = growBlock->GetLogicalSize();
|
||||
#endif
|
||||
MEM_ASSERT(growBlock->logicalSize < newSize, "Wrong block size on grow block");
|
||||
growBlock->SetLogicalSize(newSize);
|
||||
|
||||
mTotalFree -= freeBlock->GetBlockHeapUsageSize();
|
||||
|
||||
// is there still space at the end of this block for a free block?
|
||||
if ( freeBlockSize + oldAllocSize - newAllocSize > LargeBlockHeader::kLargeBlockOverhead )
|
||||
{
|
||||
LargeBlockHeader* smallFree = (LargeBlockHeader *)((char*)growBlock + newAllocSize);
|
||||
smallFree->SetPrevBlock(nil);
|
||||
smallFree->SetNextBlock(freeBlock->GetNextBlock());
|
||||
smallFree->GetNextBlock()->SetPrevBlock(smallFree);
|
||||
growBlock->SetNextBlock(smallFree);
|
||||
mTotalFree += smallFree->GetBlockHeapUsageSize();
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
smallFree->header.headerTag = kFreeBlockHeaderTag;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
growBlock->SetNextBlock(freeBlock->GetNextBlock());
|
||||
freeBlock->GetNextBlock()->SetPrevBlock(growBlock);
|
||||
}
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
growBlock->SetTrailerTag(growBlock->GetBlockSize(), kUsedBlockTrailerTag);
|
||||
growBlock->SetPaddingBytes(((newSize + 3) & ~3) - newSize);
|
||||
growBlock->FillPaddingBytes();
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
GetOwningAllocator()->AccountForResizedBlock(oldLogicalSize, newSize);
|
||||
#endif
|
||||
|
||||
UpdateLargestFreeBlock(); // we could optimize this
|
||||
|
||||
return (void *)(&growBlock->memory);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void *nsLargeHeapChunk::ShrinkBlock(LargeBlockHeader *growBlock, size_t newSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
// round the block size up to a multiple of four and add space for the header and trailer
|
||||
UInt32 newAllocSize = ((newSize + 3) & ~3) + LargeBlockHeader::kLargeBlockOverhead;
|
||||
size_t oldAllocSize = growBlock->GetBlockHeapUsageSize();
|
||||
|
||||
LargeBlockHeader* nextBlock = growBlock->GetNextBlock();
|
||||
LargeBlockHeader* smallFree = nil; // Where the recovered freeblock will go
|
||||
|
||||
// shrink this block
|
||||
#if STATS_MAC_MEMORY
|
||||
UInt32 oldLogicalSize = growBlock->GetLogicalSize();
|
||||
#endif
|
||||
MEM_ASSERT(oldAllocSize > newAllocSize, "Wrong bock size on shrink block");
|
||||
growBlock->SetLogicalSize(newSize);
|
||||
|
||||
// is the block following this block a free block?
|
||||
if (nextBlock->IsFreeBlock())
|
||||
{
|
||||
// coalesce the freed space with the following free block
|
||||
smallFree = (LargeBlockHeader *)((char *)growBlock + newAllocSize);
|
||||
mTotalFree -= nextBlock->GetBlockHeapUsageSize();
|
||||
smallFree->SetNextBlock(nextBlock->GetNextBlock());
|
||||
}
|
||||
// or is there enough space at the end of this block for a new free block?
|
||||
else if ( oldAllocSize - newAllocSize > LargeBlockHeader::kLargeBlockOverhead )
|
||||
{
|
||||
smallFree = (LargeBlockHeader *)((char *)growBlock + newAllocSize);
|
||||
smallFree->SetNextBlock(nextBlock);
|
||||
}
|
||||
|
||||
if (smallFree)
|
||||
{
|
||||
// Common actions for both cases
|
||||
smallFree->SetPrevBlock(nil);
|
||||
smallFree->GetNextBlock()->SetPrevBlock(smallFree);
|
||||
growBlock->SetNextBlock(smallFree);
|
||||
mTotalFree += smallFree->GetBlockHeapUsageSize();
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
smallFree->header.headerTag = kFreeBlockHeaderTag;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
growBlock->SetTrailerTag(growBlock->GetBlockSize(), kUsedBlockTrailerTag);
|
||||
growBlock->SetPaddingBytes(((newSize + 3) & ~3) - newSize);
|
||||
growBlock->FillPaddingBytes();
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
GetOwningAllocator()->AccountForResizedBlock(oldLogicalSize, newSize);
|
||||
#endif
|
||||
|
||||
UpdateLargestFreeBlock(); // we could optimize this
|
||||
|
||||
return (void *)(&growBlock->memory);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void* nsLargeHeapChunk::ResizeBlockInPlace(LargeBlockHeader *theBlock, size_t newSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
theBlock->SetLogicalSize(newSize);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
UInt32 newAllocSize = (newSize + 3) & ~3;
|
||||
|
||||
theBlock->SetPaddingBytes(newAllocSize - newSize);
|
||||
theBlock->FillPaddingBytes();
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
GetOwningAllocator()->AccountForResizedBlock(theBlock->header.logicalBlockSize, newSize);
|
||||
theBlock->header.logicalBlockSize = newSize;
|
||||
#endif
|
||||
|
||||
UpdateLargestFreeBlock(); // we could optimize this
|
||||
|
||||
return (void *)(&theBlock->memory);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsLargeHeapChunk::ReturnBlock(LargeBlockHeader *deadBlock)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
// we might want to coalesce this block with it's prev or next neighbor
|
||||
LargeBlockHeader *prev = deadBlock->prev;
|
||||
LargeBlockHeader *next = deadBlock->next;
|
||||
|
||||
if (prev->IsFreeBlock())
|
||||
{
|
||||
mTotalFree -= prev->GetBlockHeapUsageSize();
|
||||
prev->next = deadBlock->next;
|
||||
deadBlock = prev;
|
||||
|
||||
if (next->IsFreeBlock())
|
||||
{
|
||||
mTotalFree -= next->GetBlockHeapUsageSize();
|
||||
deadBlock->next = next->next;
|
||||
next->next->prev = deadBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
next->prev = deadBlock;
|
||||
}
|
||||
}
|
||||
else if (next->IsFreeBlock() )
|
||||
{
|
||||
mTotalFree -= next->GetBlockHeapUsageSize();
|
||||
deadBlock->next = next->next;
|
||||
next->next->prev = deadBlock;
|
||||
}
|
||||
|
||||
deadBlock->prev = nil;
|
||||
|
||||
mTotalFree += deadBlock->GetBlockHeapUsageSize();
|
||||
|
||||
UpdateLargestFreeBlock(); // we could optimize this
|
||||
|
||||
DecrementUsedBlocks();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsLargeHeapChunk::UpdateLargestFreeBlock()
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
LargeBlockHeader *thisBlock = mHead->GetNextBlock(); // head block is a dummy block
|
||||
UInt32 curMaxSize = 0;
|
||||
|
||||
while (thisBlock != mTail)
|
||||
{
|
||||
if (thisBlock->IsFreeBlock())
|
||||
{
|
||||
UInt32 blockSize = thisBlock->GetBlockHeapUsageSize();
|
||||
|
||||
if (blockSize > curMaxSize)
|
||||
curMaxSize = blockSize;
|
||||
}
|
||||
thisBlock = thisBlock->GetNextBlock();
|
||||
}
|
||||
|
||||
mLargestFreeBlock = curMaxSize;
|
||||
}
|
||||
|
|
@ -1,191 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
class nsMemAllocator;
|
||||
class nsLargeHeapChunk;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
struct LargeBlockHeader
|
||||
{
|
||||
|
||||
static LargeBlockHeader *GetBlockHeader(void *block) { return (LargeBlockHeader *)((char *)block - sizeof(LargeBlockHeader)); }
|
||||
|
||||
Boolean IsFreeBlock() { return prev == nil; }
|
||||
UInt32 GetBlockSize() { return ((UInt32)next - (UInt32)this - kLargeBlockOverhead); }
|
||||
|
||||
|
||||
UInt32 GetBlockHeapUsageSize() { return ((UInt32)next - (UInt32)this); }
|
||||
|
||||
void SetLogicalSize(UInt32 inSize) { logicalSize = inSize; }
|
||||
UInt32 GetLogicalSize() { return logicalSize; }
|
||||
|
||||
LargeBlockHeader* SkipDummyBlock() { return (LargeBlockHeader *)((UInt32)this + kLargeBlockOverhead); }
|
||||
|
||||
|
||||
LargeBlockHeader* GetNextBlock() { return next; }
|
||||
LargeBlockHeader* GetPrevBlock() { return prev; }
|
||||
|
||||
void SetNextBlock(LargeBlockHeader *inNext) { next = inNext; }
|
||||
void SetPrevBlock(LargeBlockHeader *inPrev) { prev = inPrev; }
|
||||
|
||||
void SetOwningChunk(nsHeapChunk *chunk) { header.owningChunk = chunk; }
|
||||
nsLargeHeapChunk* GetOwningChunk() { return (nsLargeHeapChunk *)(header.owningChunk); }
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
enum {
|
||||
kBlockPaddingBytes = 'ðððð'
|
||||
};
|
||||
|
||||
void SetPaddingBytes(UInt32 padding) { paddingBytes = padding; }
|
||||
void FillPaddingBytes() {
|
||||
long *lastLong = (long *)((char *)&memory + GetBlockSize() - sizeof(long));
|
||||
UInt32 mask = (1 << (8 * paddingBytes)) - 1;
|
||||
|
||||
*lastLong &= ~mask;
|
||||
*lastLong |= (mask & kBlockPaddingBytes);
|
||||
}
|
||||
Boolean CheckPaddingBytes() {
|
||||
long *lastLong = (long *)((char *)&memory + GetBlockSize() - sizeof(long));
|
||||
UInt32 mask = (1 << (8 * paddingBytes)) - 1;
|
||||
return (*lastLong & mask) == (mask & kBlockPaddingBytes);
|
||||
}
|
||||
UInt32 GetPaddingBytes() { return paddingBytes; }
|
||||
|
||||
void ZapBlockContents(UInt8 pattern) { memset(&memory, pattern, GetBlockSize()); }
|
||||
|
||||
// inline, so won't crash if this is a bad block
|
||||
Boolean HasHeaderTag(MemoryBlockTag inHeaderTag)
|
||||
{ return header.headerTag == inHeaderTag; }
|
||||
void SetHeaderTag(MemoryBlockTag inHeaderTag)
|
||||
{ header.headerTag = inHeaderTag; }
|
||||
void SetTrailerTag(UInt32 blockSize, MemoryBlockTag theTag)
|
||||
{
|
||||
MemoryBlockTrailer *trailer = (MemoryBlockTrailer *)((char *)&memory + blockSize);
|
||||
trailer->trailerTag = theTag;
|
||||
}
|
||||
Boolean HasTrailerTag(UInt32 blockSize, MemoryBlockTag theTag)
|
||||
{
|
||||
MemoryBlockTrailer *trailer = (MemoryBlockTrailer *)((char *)&memory + blockSize);
|
||||
return (trailer->trailerTag == theTag);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const UInt32 kLargeBlockOverhead;
|
||||
|
||||
LargeBlockHeader *next;
|
||||
LargeBlockHeader *prev;
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
UInt32 paddingBytes;
|
||||
#endif
|
||||
|
||||
UInt32 logicalSize;
|
||||
MemoryBlockHeader header; // this must be the last variable before memory
|
||||
|
||||
char memory[];
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class nsLargeHeapAllocator : public nsMemAllocator
|
||||
{
|
||||
private:
|
||||
|
||||
typedef nsMemAllocator Inherited;
|
||||
|
||||
|
||||
public:
|
||||
nsLargeHeapAllocator(size_t minBlockSize, size_t maxBlockSize);
|
||||
~nsLargeHeapAllocator();
|
||||
|
||||
|
||||
void * AllocatorMakeBlock(size_t blockSize);
|
||||
void AllocatorFreeBlock(void *freeBlock);
|
||||
void * AllocatorResizeBlock(void *block, size_t newSize);
|
||||
size_t AllocatorGetBlockSize(void *thisBlock);
|
||||
|
||||
nsHeapChunk* AllocateChunk(size_t requestedBlockSize);
|
||||
void FreeChunk(nsHeapChunk *chunkToFree);
|
||||
|
||||
UInt32 GetPaddedBlockSize(UInt32 blockSize) { return ((blockSize + 3) & ~3) + LargeBlockHeader::kLargeBlockOverhead; }
|
||||
|
||||
protected:
|
||||
|
||||
UInt32 mBaseChunkPercentage;
|
||||
UInt32 mBestTempChunkSize;
|
||||
UInt32 mSmallestTempChunkSize;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class nsLargeHeapChunk : public nsHeapChunk
|
||||
{
|
||||
public:
|
||||
|
||||
nsLargeHeapChunk( nsMemAllocator *inOwningAllocator,
|
||||
Size heapSize);
|
||||
~nsLargeHeapChunk();
|
||||
|
||||
LargeBlockHeader* GetHeadBlock() { return mHead; }
|
||||
|
||||
LargeBlockHeader* GetSpaceForBlock(UInt32 roundedBlockSize);
|
||||
|
||||
void * GrowBlock(LargeBlockHeader *growBlock, size_t newSize);
|
||||
void * ShrinkBlock(LargeBlockHeader *shrinkBlock, size_t newSize);
|
||||
void * ResizeBlockInPlace(LargeBlockHeader *theBlock, size_t newSize);
|
||||
|
||||
void ReturnBlock(LargeBlockHeader *deadBlock);
|
||||
|
||||
UInt32 GetLargestFreeBlock() { return mLargestFreeBlock; }
|
||||
|
||||
protected:
|
||||
|
||||
void UpdateLargestFreeBlock();
|
||||
|
||||
UInt32 mTotalFree;
|
||||
UInt32 mLargestFreeBlock; // heap useage for largest block we can allocate
|
||||
|
||||
LargeBlockHeader* mTail;
|
||||
LargeBlockHeader mHead[];
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1,292 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <MacMemory.h>
|
||||
|
||||
#include "nsMemAllocator.h"
|
||||
#include "nsAllocatorManager.h"
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsHeapChunk::nsHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize)
|
||||
: mOwningAllocator(inOwningAllocator)
|
||||
, mNextChunk(nil)
|
||||
, mHeapSize(heapSize)
|
||||
, mUsedBlocks(0)
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
, mSignature(kChunkSignature)
|
||||
#endif
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsHeapChunk::~nsHeapChunk()
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsMemAllocator::nsMemAllocator(EAllocatorType allocatorType, size_t minBlockSize, size_t maxBlockSize)
|
||||
: mAllocatorType(allocatorType)
|
||||
, mFirstChunk(nil)
|
||||
, mLastChunk(nil)
|
||||
, mNumChunks(0)
|
||||
, mMinBlockSize(minBlockSize)
|
||||
, mMaxBlockSize(maxBlockSize)
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
, mSignature(kMemAllocatorSignature)
|
||||
#endif
|
||||
#if STATS_MAC_MEMORY
|
||||
, mCurBlockCount(0)
|
||||
, mMaxBlockCount(0)
|
||||
, mCurBlockSpaceUsed(0)
|
||||
, mMaxBlockSpaceUsed(0)
|
||||
, mCurHeapSpaceUsed(0)
|
||||
, mMaxHeapSpaceUsed(0)
|
||||
, mCurSubheapCount(0)
|
||||
, mMaxSubheapCount(0)
|
||||
, mCountHistogram(NULL)
|
||||
#endif
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
#if STATS_MAC_MEMORY
|
||||
mCountHistogram = (UInt32 *)NewPtrClear(sizeof(UInt32) * (maxBlockSize - minBlockSize + 1));
|
||||
// failure is ok
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsMemAllocator::~nsMemAllocator()
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
#if STATS_MAC_MEMORY
|
||||
if (mCountHistogram)
|
||||
DisposePtr((Ptr)mCountHistogram);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsMemAllocator::AddToChunkList(nsHeapChunk *inNewChunk)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
if (mLastChunk)
|
||||
mLastChunk->SetNextChunk(inNewChunk);
|
||||
else
|
||||
mFirstChunk = inNewChunk;
|
||||
|
||||
mLastChunk = inNewChunk;
|
||||
|
||||
mNumChunks ++;
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
mCurSubheapCount ++;
|
||||
if (mCurSubheapCount > mMaxSubheapCount)
|
||||
mMaxSubheapCount = mCurSubheapCount;
|
||||
|
||||
mCurHeapSpaceUsed += inNewChunk->GetChunkSize();
|
||||
if (mCurHeapSpaceUsed > mMaxHeapSpaceUsed)
|
||||
mMaxHeapSpaceUsed = mCurHeapSpaceUsed;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsMemAllocator::RemoveFromChunkList(nsHeapChunk *inChunk)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
nsHeapChunk *prevChunk = nil;
|
||||
nsHeapChunk *nextChunk = nil;
|
||||
nsHeapChunk *thisChunk = mFirstChunk;
|
||||
|
||||
while (thisChunk)
|
||||
{
|
||||
nextChunk = thisChunk->GetNextChunk();
|
||||
|
||||
if (thisChunk == inChunk)
|
||||
break;
|
||||
|
||||
prevChunk = thisChunk;
|
||||
thisChunk = nextChunk;
|
||||
}
|
||||
|
||||
if (thisChunk)
|
||||
{
|
||||
if (prevChunk)
|
||||
prevChunk->SetNextChunk(nextChunk);
|
||||
|
||||
if (mFirstChunk == thisChunk)
|
||||
mFirstChunk = nextChunk;
|
||||
|
||||
if (mLastChunk == thisChunk)
|
||||
mLastChunk = prevChunk;
|
||||
}
|
||||
|
||||
mNumChunks --;
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
mCurSubheapCount --;
|
||||
|
||||
mCurHeapSpaceUsed -= inChunk->GetChunkSize();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsMemAllocator::AccountForNewBlock(size_t logicalSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
mCurBlockCount ++;
|
||||
|
||||
if (mCurBlockCount > mMaxBlockCount)
|
||||
mMaxBlockCount = mCurBlockCount;
|
||||
|
||||
mCurBlockSpaceUsed += logicalSize;
|
||||
|
||||
if (mCurBlockSpaceUsed > mMaxBlockSpaceUsed)
|
||||
mMaxBlockSpaceUsed = mCurBlockSpaceUsed;
|
||||
|
||||
if (mCountHistogram)
|
||||
{
|
||||
mCountHistogram[logicalSize - mMinBlockSize]++;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsMemAllocator::AccountForResizedBlock(size_t oldLogicalSize, size_t newLogicalSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
mCurBlockSpaceUsed -= oldLogicalSize;
|
||||
mCurBlockSpaceUsed += newLogicalSize;
|
||||
|
||||
if (mCurBlockSpaceUsed > mMaxBlockSpaceUsed)
|
||||
mMaxBlockSpaceUsed = mCurBlockSpaceUsed;
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsMemAllocator::AccountForFreedBlock(size_t logicalSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
mCurBlockCount --;
|
||||
mCurBlockSpaceUsed -= logicalSize;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsMemAllocator::DumpHeapUsage(PRFileDesc *outFile)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
char outString[ 1024 ];
|
||||
|
||||
sprintf(outString, "%04ld ", mMaxBlockSize);
|
||||
|
||||
WriteString(outFile, outString);
|
||||
|
||||
char *p = outString;
|
||||
SInt32 numStars = mMaxHeapSpaceUsed / 1024;
|
||||
if (numStars > 1021)
|
||||
numStars = 1021;
|
||||
|
||||
for (SInt32 i = 0; i < numStars; i ++)
|
||||
*p++ = '*';
|
||||
|
||||
if (numStars == 1021)
|
||||
*p++ = 'É';
|
||||
*p++ = '\n';
|
||||
*p = '\0';
|
||||
|
||||
WriteString(outFile, outString);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsMemAllocator::DumpMemoryStats(PRFileDesc *outFile)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
char outString[ 1024 ];
|
||||
|
||||
sprintf(outString, "Stats for heap of blocks %ld - %ld bytes\n", mMinBlockSize, mMaxBlockSize);
|
||||
|
||||
WriteString ( outFile, "\n\n--------------------------------------------------------------------------------\n" );
|
||||
WriteString(outFile, outString);
|
||||
WriteString ( outFile, "--------------------------------------------------------------------------------\n" );
|
||||
WriteString ( outFile, " Current Max\n" );
|
||||
WriteString ( outFile, " ---------- -------\n" );
|
||||
sprintf( outString, "Num chunks: %10d %10d\n", mCurSubheapCount, mMaxSubheapCount);
|
||||
WriteString ( outFile, outString );
|
||||
sprintf( outString, "Chunk total: %10d %10d\n", mCurHeapSpaceUsed, mMaxHeapSpaceUsed);
|
||||
WriteString ( outFile, outString );
|
||||
sprintf( outString, "Block space: %10d %10d\n", mCurBlockSpaceUsed, mMaxBlockSpaceUsed );
|
||||
WriteString ( outFile, outString );
|
||||
sprintf( outString, "Blocks used: %10d %10d\n", mCurBlockCount, mMaxBlockCount );
|
||||
WriteString ( outFile, outString );
|
||||
WriteString ( outFile, " -------\n" );
|
||||
sprintf( outString, "%s of allocated space used: %10.2f\n", "%", 100.0 * mMaxBlockSpaceUsed / mMaxHeapSpaceUsed );
|
||||
WriteString ( outFile, outString );
|
||||
|
||||
|
||||
if (mCountHistogram)
|
||||
{
|
||||
WriteString ( outFile, "\n\n");
|
||||
WriteString ( outFile, "Block size Total allocations\n------------------------------\n" );
|
||||
|
||||
for (UInt32 i = mMinBlockSize; i <= mMaxBlockSize; i ++)
|
||||
{
|
||||
sprintf(outString,"%5d %10d\n", i, mCountHistogram[i - mMinBlockSize]);
|
||||
WriteString ( outFile, outString );
|
||||
}
|
||||
|
||||
WriteString(outFile, "------------------------------\n");
|
||||
}
|
||||
|
||||
WriteString ( outFile, "\n\n");
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,243 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
#include "prio.h"
|
||||
#endif
|
||||
|
||||
class nsMemAllocator;
|
||||
class nsHeapChunk;
|
||||
|
||||
|
||||
enum {
|
||||
kFreeBlockHeaderTag = 'FREE',
|
||||
kFreeBlockTrailerTag = 'free',
|
||||
kUsedBlockHeaderTag = 'USED',
|
||||
kUsedBlockTrailerTag = 'used',
|
||||
kDummyBlockHeaderTag = 'D\'oh',
|
||||
kRefdBlockHeaderTag = 'REFD',
|
||||
kRefdBlockTrailerTag = 'refd',
|
||||
kUsedMemoryFillPattern = 0xDB,
|
||||
kFreeMemoryFillPattern = 0xEF //if you don't want to crash hard, change to 0x04 or 0x05,
|
||||
};
|
||||
|
||||
|
||||
typedef UInt32 MemoryBlockTag;
|
||||
|
||||
|
||||
struct MemoryBlockHeader
|
||||
{
|
||||
nsHeapChunk *owningChunk;
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
// it sucks putting an extra data member in here which affects stats, but there is no other
|
||||
// way to store the logical size of each block.
|
||||
size_t logicalBlockSize;
|
||||
#endif
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
//MemoryBlockHeader *next;
|
||||
//MemoryBlockHeader *prev;
|
||||
UInt32 blockID;
|
||||
MemoryBlockTag headerTag; // put this as the last thing before memory
|
||||
#endif
|
||||
|
||||
static MemoryBlockHeader* GetHeaderFromBlock(void *block) { return (MemoryBlockHeader*)((char *)block - sizeof(MemoryBlockHeader)); }
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
// inline, so won't crash if this is a bad block
|
||||
Boolean HasHeaderTag(MemoryBlockTag inHeaderTag) { return (headerTag == inHeaderTag); }
|
||||
void SetHeaderTag(MemoryBlockTag inHeaderTag) { headerTag = inHeaderTag; }
|
||||
#else
|
||||
// stubs
|
||||
Boolean HasHeaderTag(MemoryBlockTag inHeaderTag){ return true; }
|
||||
void SetHeaderTag(MemoryBlockTag inHeaderTag){}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct MemoryBlockTrailer {
|
||||
MemoryBlockTag trailerTag;
|
||||
};
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
#define MEMORY_BLOCK_TAILER_SIZE sizeof(struct MemoryBlockTrailer)
|
||||
#else
|
||||
#define MEMORY_BLOCK_TAILER_SIZE 0
|
||||
#endif /* DEBUG_HEAP_INTEGRITY */
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class nsHeapChunk
|
||||
{
|
||||
public:
|
||||
|
||||
nsHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize);
|
||||
~nsHeapChunk();
|
||||
|
||||
nsHeapChunk* GetNextChunk() const { return mNextChunk; }
|
||||
void SetNextChunk(nsHeapChunk *inChunk) { mNextChunk = inChunk; }
|
||||
|
||||
nsMemAllocator* GetOwningAllocator() const { return mOwningAllocator; }
|
||||
|
||||
void IncrementUsedBlocks() { mUsedBlocks ++; }
|
||||
void DecrementUsedBlocks() { mUsedBlocks -- ; MEM_ASSERT(mUsedBlocks >= 0, "Bad chunk block count"); }
|
||||
|
||||
Boolean IsEmpty() const { return mUsedBlocks == 0; }
|
||||
|
||||
UInt32 GetChunkSize() { return mHeapSize; }
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
Boolean IsGoodChunk() { return mSignature == kChunkSignature; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
enum {
|
||||
kChunkSignature = 'Chnk'
|
||||
};
|
||||
|
||||
OSType mSignature;
|
||||
#endif
|
||||
nsMemAllocator *mOwningAllocator;
|
||||
nsHeapChunk *mNextChunk;
|
||||
UInt32 mUsedBlocks;
|
||||
UInt32 mHeapSize;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class nsMemAllocator
|
||||
{
|
||||
public:
|
||||
|
||||
enum EAllocatorType {
|
||||
eAllocatorTypeFixed,
|
||||
eAllocatorTypeSmall,
|
||||
eAllocatorTypeLarge
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
nsMemAllocator(EAllocatorType allocatorType, size_t minBlockSize, size_t maxBlockSize);
|
||||
~nsMemAllocator();
|
||||
|
||||
EAllocatorType GetAllocatorType() const { return mAllocatorType; }
|
||||
|
||||
Boolean IsGoodAllocator()
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
{ return mSignature == kMemAllocatorSignature; }
|
||||
#else
|
||||
{ return true; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
void AddToChunkList(nsHeapChunk *inNewChunk);
|
||||
void RemoveFromChunkList(nsHeapChunk *inChunk);
|
||||
|
||||
enum {
|
||||
kMemAllocatorSignature = 'ARSE' // Allocators R Supremely Efficient
|
||||
};
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
OSType mSignature; // signature for debugging
|
||||
#endif
|
||||
|
||||
nsHeapChunk *mFirstChunk; // pointer to first subheap managed by this allocator
|
||||
nsHeapChunk *mLastChunk; // pointer to last subheap managed by this allocator
|
||||
|
||||
UInt32 mMinBlockSize; // smallest block normally handled by this allocator (inclusive)
|
||||
UInt32 mMaxBlockSize; // largest block handled by this allocator (inclusive)
|
||||
|
||||
UInt32 mNumChunks; // number of chunks in list
|
||||
|
||||
UInt32 mBaseChunkSize; // size of subheap allocated at startup
|
||||
UInt32 mTempChunkSize; // size of additional subheaps
|
||||
|
||||
|
||||
const EAllocatorType mAllocatorType;
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
|
||||
public:
|
||||
|
||||
void AccountForNewBlock(size_t logicalSize);
|
||||
void AccountForFreedBlock(size_t logicalSize);
|
||||
void AccountForResizedBlock(size_t oldLogicalSize, size_t newLogicalSize);
|
||||
|
||||
void DumpMemoryStats(PRFileDesc *statsFile);
|
||||
void DumpHeapUsage(PRFileDesc *statsFile);
|
||||
|
||||
UInt32 GetMaxHeapUsage() { return mMaxHeapSpaceUsed; }
|
||||
|
||||
private:
|
||||
|
||||
UInt32 mCurBlockCount; // number of malloc blocks allocated now
|
||||
UInt32 mMaxBlockCount; // max number of malloc blocks allocated
|
||||
|
||||
UInt32 mCurBlockSpaceUsed; // sum of logical size of allocated blocks
|
||||
UInt32 mMaxBlockSpaceUsed; // max of sum of logical size of allocated blocks
|
||||
|
||||
UInt32 mCurHeapSpaceUsed; // sum of physical size of allocated chunks
|
||||
UInt32 mMaxHeapSpaceUsed; // max of sum of logical size of allocated chunks
|
||||
|
||||
UInt32 mCurSubheapCount; // current number of subheaps allocated by this allocator
|
||||
UInt32 mMaxSubheapCount; // max number of subheaps allocated by this allocator
|
||||
|
||||
UInt32* mCountHistogram; // cumulative hist of frequencies
|
||||
|
||||
// the difference between mCurBlockSpaceUsed and mCurHeapSpaceUsed is
|
||||
// the allocator overhead, which consists of:
|
||||
//
|
||||
// 1. Block overhead (rounding, headers & trailers)
|
||||
// 2. Unused block space in chunks
|
||||
// 3. Chunk overhead (rounding, headers & trailers)
|
||||
//
|
||||
// This is a reasonable measure of the space efficiency of these allocators
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <MacMemory.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *malloc(size_t blockSize);
|
||||
void free(void *deadBlock);
|
||||
void* realloc(void* block, size_t newSize);
|
||||
void *calloc(size_t nele, size_t elesize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// NewPtr implementation of malloc/free, for testing purposes
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void *malloc(size_t blockSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
return (void *)::NewPtr(blockSize);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void free(void *deadBlock)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
if (deadBlock)
|
||||
::DisposePtr((Ptr)deadBlock);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void* realloc(void* block, size_t newSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
::SetPtrSize((Ptr)block, newSize);
|
||||
if (MemError() == noErr)
|
||||
return block;
|
||||
|
||||
void* newBlock = ::NewPtr(newSize);
|
||||
if (!newBlock) return nil;
|
||||
|
||||
BlockMoveData(block, newBlock, newSize); // might copy off the end of block,
|
||||
// but who cares?
|
||||
|
||||
return newBlock;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void *calloc(size_t nele, size_t elesize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
size_t space = nele * elesize;
|
||||
void *newBlock = ::malloc(space);
|
||||
if (newBlock)
|
||||
memset(newBlock, 0, space);
|
||||
return newBlock;
|
||||
}
|
||||
|
|
@ -1,676 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#include <new.h> // for placement new
|
||||
#include <MacMemory.h>
|
||||
|
||||
#include "nsMemAllocator.h"
|
||||
#include "nsAllocatorManager.h"
|
||||
#include "nsSmallHeapAllocator.h"
|
||||
|
||||
const UInt32 SmallHeapBlock::kBlockOverhead = sizeof(SmallHeapBlock) + MEMORY_BLOCK_TAILER_SIZE;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsSmallHeapAllocator::nsSmallHeapAllocator(size_t minBlockSize, size_t maxBlockSize)
|
||||
: nsMemAllocator(eAllocatorTypeSmall, minBlockSize, maxBlockSize)
|
||||
, mChunkWithSpace(nil)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
// this gets rounded up when we allocate chunks
|
||||
mBaseChunkSize = mTempChunkSize = 64 * (mMaxBlockSize + SmallHeapBlock::kBlockOverhead); //(nsAllocatorManager::kChunkSizeMultiple);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsSmallHeapAllocator::~nsSmallHeapAllocator()
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void *nsSmallHeapAllocator::AllocatorMakeBlock(size_t blockSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
// try the cheap way first
|
||||
if (mChunkWithSpace)
|
||||
{
|
||||
void *foundBlock = mChunkWithSpace->GetSpaceForBlock(blockSize);
|
||||
if (foundBlock) return foundBlock;
|
||||
}
|
||||
|
||||
nsSmallHeapChunk *chunk = (nsSmallHeapChunk *)mFirstChunk;
|
||||
|
||||
// walk through all of our chunks, trying to allocate memory from somewhere
|
||||
while (chunk)
|
||||
{
|
||||
void *theBlock = chunk->GetSpaceForBlock(blockSize);
|
||||
|
||||
if (theBlock)
|
||||
return theBlock;
|
||||
|
||||
chunk = (nsSmallHeapChunk *)chunk->GetNextChunk();
|
||||
} // while (chunk != nil)
|
||||
|
||||
chunk = (nsSmallHeapChunk *)AllocateChunk(blockSize);
|
||||
if (!chunk) return nil;
|
||||
|
||||
mChunkWithSpace = chunk;
|
||||
return chunk->GetSpaceForBlock(blockSize);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsSmallHeapAllocator::AllocatorFreeBlock(void *freeBlock)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
SmallHeapBlock *deadBlock = SmallHeapBlock::GetBlockHeader(freeBlock);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(deadBlock->HasHeaderTag(kUsedBlockHeaderTag), "Bad block header on free");
|
||||
MEM_ASSERT(deadBlock->HasTrailerTag(deadBlock->GetBlockSize(), kUsedBlockTrailerTag), "Bad block trailer on free");
|
||||
MEM_ASSERT(deadBlock->CheckPaddingBytes(), "Block has overwritten its bounds");
|
||||
|
||||
deadBlock->ZapBlockContents(kFreeMemoryFillPattern);
|
||||
#endif
|
||||
|
||||
nsSmallHeapChunk *chunk = deadBlock->GetOwningChunk();
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
deadBlock->SetHeaderTag(kFreeBlockHeaderTag);
|
||||
deadBlock->SetTrailerTag(deadBlock->GetBlockSize(), kFreeBlockTrailerTag);
|
||||
#endif
|
||||
|
||||
chunk->ReturnBlock(deadBlock);
|
||||
|
||||
// if this chunk is completely empty and it's not the first chunk then free it
|
||||
if (chunk->IsEmpty() && chunk!= mFirstChunk)
|
||||
{
|
||||
if (chunk == mChunkWithSpace)
|
||||
mChunkWithSpace = nil;
|
||||
|
||||
FreeChunk(chunk);
|
||||
}
|
||||
else
|
||||
{
|
||||
mChunkWithSpace = chunk; // we know is has some space now, probably
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void *nsSmallHeapAllocator::AllocatorResizeBlock(void *block, size_t newSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
SmallHeapBlock *blockHeader = SmallHeapBlock::GetBlockHeader(block);
|
||||
nsSmallHeapChunk *chunk = blockHeader->GetOwningChunk();
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(blockHeader->HasHeaderTag(kUsedBlockHeaderTag), "Bad block header on realloc");
|
||||
MEM_ASSERT(blockHeader->HasTrailerTag(blockHeader->GetBlockSize(), kUsedBlockTrailerTag), "Bad block trailer on realloc");
|
||||
MEM_ASSERT(blockHeader->CheckPaddingBytes(), "Block has overwritten its bounds");
|
||||
#endif
|
||||
|
||||
UInt32 newAllocSize = (newSize + 3) & ~3;
|
||||
|
||||
// we can resize this block to any size, provided it fits.
|
||||
|
||||
if (newAllocSize < blockHeader->GetBlockSize()) // shrinking
|
||||
{
|
||||
return chunk->ShrinkBlock(blockHeader, newSize);
|
||||
}
|
||||
else if (newAllocSize > blockHeader->GetBlockSize()) // growing
|
||||
{
|
||||
return chunk->GrowBlock(blockHeader, newSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
return chunk->ResizeBlockInPlace(blockHeader, newSize);
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
size_t nsSmallHeapAllocator::AllocatorGetBlockSize(void *thisBlock)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
SmallHeapBlock *allocBlock = SmallHeapBlock::GetBlockHeader(thisBlock);
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(allocBlock->HasHeaderTag(kUsedBlockHeaderTag), "Bad block header on get block size");
|
||||
#endif
|
||||
return allocBlock->GetBlockSize();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsHeapChunk *nsSmallHeapAllocator::AllocateChunk(size_t blockSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
UInt32 minChunkSize = ((blockSize + 3) & ~3) + sizeof(nsSmallHeapChunk) + 3 * SmallHeapBlock::kBlockOverhead;
|
||||
|
||||
if (minChunkSize < mBaseChunkSize)
|
||||
minChunkSize = mBaseChunkSize;
|
||||
|
||||
Size actualChunkSize;
|
||||
Ptr chunkMemory = nsAllocatorManager::GetAllocatorManager()->AllocateSubheap(mBaseChunkSize, actualChunkSize);
|
||||
if (!chunkMemory) return nil;
|
||||
|
||||
// use placement new to initialize the chunk in the memory block
|
||||
nsHeapChunk *newHeapChunk = new (chunkMemory) nsSmallHeapChunk(this, actualChunkSize);
|
||||
if (newHeapChunk)
|
||||
AddToChunkList(newHeapChunk);
|
||||
|
||||
return newHeapChunk;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsSmallHeapAllocator::FreeChunk(nsHeapChunk *chunkToFree)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
RemoveFromChunkList(chunkToFree);
|
||||
// we used placement new to make it, so we have to delete like this
|
||||
nsSmallHeapChunk *thisChunk = (nsSmallHeapChunk *)chunkToFree;
|
||||
thisChunk->~nsSmallHeapChunk();
|
||||
|
||||
nsAllocatorManager::GetAllocatorManager()->FreeSubheap((Ptr)thisChunk);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsSmallHeapChunk::nsSmallHeapChunk(
|
||||
nsMemAllocator *inOwningAllocator,
|
||||
Size heapSize)
|
||||
: nsHeapChunk(inOwningAllocator, heapSize)
|
||||
, mOverflow(nil)
|
||||
, mTotalFree(0)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
// init the bin ptrs
|
||||
for (UInt32 count = 0; count < kDefaultSmallHeapBins; ++count )
|
||||
mBins[count] = nil;
|
||||
|
||||
// mark how much we can actually store in the heap
|
||||
heapSize -= sizeof(nsSmallHeapChunk); // subtract heap overhead
|
||||
mHeapSize = heapSize - 3 * SmallHeapBlock::kBlockOverhead;
|
||||
|
||||
SmallHeapBlock *newRawBlockHeader = mMemory;
|
||||
|
||||
// The first few bytes of the block are a dummy header
|
||||
// which is a block of size zero that is always allocated.
|
||||
// This allows our coalesce code to work without modification
|
||||
// on the edge case of coalescing the first real block.
|
||||
|
||||
newRawBlockHeader->SetPrevBlock(nil);
|
||||
newRawBlockHeader->SetBlockSize(0);
|
||||
newRawBlockHeader->SetBlockUsed();
|
||||
newRawBlockHeader->SetOwningChunk(nil);
|
||||
|
||||
SmallHeapBlock *newFreeOverflowBlock = newRawBlockHeader->GetNextBlock();
|
||||
|
||||
newFreeOverflowBlock->SetPrevBlock(newRawBlockHeader);
|
||||
newFreeOverflowBlock->SetBlockSize(heapSize - 3 * SmallHeapBlock::kBlockOverhead);
|
||||
|
||||
// The same is true for the last few bytes in the block as well.
|
||||
|
||||
SmallHeapBlock *newRawBlockTrailer = (SmallHeapBlock *)(((Ptr)newRawBlockHeader) + heapSize - SmallHeapBlock::kBlockOverhead);
|
||||
newRawBlockTrailer->SetPrevBlock(newFreeOverflowBlock);
|
||||
newRawBlockTrailer->SetBlockSize(0xFFFFFFFF);
|
||||
newRawBlockTrailer->SetBlockUsed();
|
||||
newRawBlockTrailer->SetOwningChunk(nil);
|
||||
|
||||
AddBlockToFreeList(newFreeOverflowBlock);
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
mInitialFree = mTotalFree;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsSmallHeapChunk::~nsSmallHeapChunk()
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
MEM_ASSERT(mUsedBlocks != 0 || mTotalFree == mInitialFree, "Bad free measure");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void *nsSmallHeapChunk::GetSpaceForBlock(size_t blockSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
// Round up allocation to nearest 4 bytes.
|
||||
UInt32 roundedBlockSize = (blockSize + 3) & ~3;
|
||||
MEM_ASSERT(roundedBlockSize <= nsSmallHeapChunk::kMaximumBlockSize, "Block is too big for this allocator!");
|
||||
|
||||
if (mTotalFree < roundedBlockSize) return nil;
|
||||
//Boolean expectFailure = (mTotalFree < roundedBlockSize);
|
||||
|
||||
// Try to find the best fit in one of the bins.
|
||||
UInt32 startingBinNum = (roundedBlockSize - kDefaultSmallHeadMinSize) >> 2;
|
||||
|
||||
SmallHeapBlock **currentBin = GetBins(startingBinNum);
|
||||
SmallHeapBlock *currentBinValue = *currentBin;
|
||||
SmallHeapBlock *allocatedBlock = nil;
|
||||
|
||||
// If the current bin has something in it,
|
||||
// then use it for our allocation.
|
||||
|
||||
if (currentBinValue)
|
||||
{
|
||||
RemoveBlockFromFreeList(currentBinValue);
|
||||
MEM_ASSERT(currentBinValue->GetBlockSize() >= roundedBlockSize, "Got a smaller block than requested");
|
||||
allocatedBlock = currentBinValue;
|
||||
goto done;
|
||||
}
|
||||
|
||||
// Otherwise, try to carve up an existing larger block.
|
||||
|
||||
UInt32 remainingBins = kDefaultSmallHeapBins - startingBinNum - 1;
|
||||
SmallHeapBlock *blockToCarve = nil;
|
||||
|
||||
while (remainingBins--)
|
||||
{
|
||||
currentBin++;
|
||||
currentBinValue = *currentBin;
|
||||
|
||||
if (currentBinValue != nil)
|
||||
{
|
||||
blockToCarve = currentBinValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Try carving up up a block from the overflow bin.
|
||||
|
||||
if (blockToCarve == nil)
|
||||
blockToCarve = GetOverflow();
|
||||
|
||||
while (blockToCarve != nil)
|
||||
{
|
||||
SInt32 blockToCarveSize = blockToCarve->GetBlockSize();
|
||||
|
||||
// If the owerflow block is big enough to house the
|
||||
// allocation, then use it.
|
||||
|
||||
if (blockToCarveSize >= roundedBlockSize)
|
||||
{
|
||||
// Remove the block from the free list... we will
|
||||
// be using it for the allocation...
|
||||
|
||||
RemoveBlockFromFreeList(blockToCarve);
|
||||
|
||||
// If taking our current allocation out of
|
||||
// the overflow block would still leave enough
|
||||
// room for another allocation out of the
|
||||
// block, then split the block up.
|
||||
|
||||
SInt32 leftovers = blockToCarveSize - roundedBlockSize - SmallHeapBlock::kBlockOverhead;
|
||||
|
||||
if (leftovers >= kDefaultSmallHeadMinSize)
|
||||
{
|
||||
SmallHeapBlock *nextBlock = blockToCarve->GetNextBlock();
|
||||
|
||||
// Create a new block out of the leftovers
|
||||
|
||||
SmallHeapBlock *leftoverBlock = (SmallHeapBlock *)((char *)blockToCarve + roundedBlockSize + SmallHeapBlock::kBlockOverhead);
|
||||
|
||||
// Add the block to linked list of blocks in this raw
|
||||
// allocation chunk.
|
||||
|
||||
nextBlock->SetPrevBlock(leftoverBlock);
|
||||
|
||||
blockToCarve->SetBlockSize(roundedBlockSize);
|
||||
blockToCarve->SetBlockUsed();
|
||||
|
||||
leftoverBlock->SetPrevBlock(blockToCarve);
|
||||
leftoverBlock->SetBlockSize(leftovers);
|
||||
|
||||
// And add the block to a free list, which will either be
|
||||
// one of the sized bins or the overflow list, depending
|
||||
// on its size.
|
||||
|
||||
AddBlockToFreeList(leftoverBlock);
|
||||
}
|
||||
// else...
|
||||
// if we didn't carve up the block, then we are returning a block that is bigger
|
||||
// than the requested size. That's fine, we just need to be careful about where
|
||||
// to put the trailer tag, because we only know the allocated size, and not the
|
||||
// requested size.
|
||||
|
||||
allocatedBlock = blockToCarve;
|
||||
goto done;
|
||||
}
|
||||
|
||||
blockToCarve = blockToCarve->GetNextFree();
|
||||
}
|
||||
|
||||
return nil;
|
||||
|
||||
done:
|
||||
|
||||
allocatedBlock->SetOwningChunk(this);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
allocatedBlock->SetHeaderTag(kUsedBlockHeaderTag);
|
||||
allocatedBlock->SetTrailerTag(allocatedBlock->GetBlockSize(), kUsedBlockTrailerTag);
|
||||
allocatedBlock->ZapBlockContents(kUsedMemoryFillPattern);
|
||||
allocatedBlock->SetPaddingBytes(roundedBlockSize - blockSize);
|
||||
allocatedBlock->FillPaddingBytes();
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
allocatedBlock->SetLogicalBlockSize(blockSize);
|
||||
GetOwningAllocator()->AccountForNewBlock(blockSize);
|
||||
#endif
|
||||
|
||||
//MEM_ASSERT(!expectFailure, "I though this would fail!");
|
||||
|
||||
IncrementUsedBlocks();
|
||||
return &allocatedBlock->memory;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void *nsSmallHeapChunk::GrowBlock(SmallHeapBlock *growBlock, size_t newSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
UInt32 newAllocSize = (newSize + 3) & ~3;
|
||||
|
||||
SmallHeapBlock *blockToCarve = growBlock->GetNextBlock();
|
||||
|
||||
if (! blockToCarve->IsBlockUsed())
|
||||
{
|
||||
UInt32 oldPhysicalSize = growBlock->GetBlockHeapUsage();
|
||||
UInt32 newPhysicalSize = SmallHeapBlock::kBlockOverhead + newAllocSize;
|
||||
|
||||
UInt32 blockToCarveSize = blockToCarve->GetBlockSize();
|
||||
UInt32 blockToCarvePhysicalSize = blockToCarve->GetBlockHeapUsage();
|
||||
|
||||
SInt32 leftovers = (SInt32)oldPhysicalSize + blockToCarvePhysicalSize - newPhysicalSize;
|
||||
|
||||
// enough space to grow into the free block?
|
||||
if (leftovers < 0)
|
||||
return nil;
|
||||
|
||||
// Remove the block from the free list... we will
|
||||
// be using it for the allocation...
|
||||
|
||||
RemoveBlockFromFreeList(blockToCarve);
|
||||
|
||||
// If taking our current allocation out of
|
||||
// the overflow block would still leave enough
|
||||
// room for another allocation out of the
|
||||
// block, then split the block up.
|
||||
|
||||
if (leftovers >= kDefaultSmallHeadMinSize + SmallHeapBlock::kBlockOverhead)
|
||||
{
|
||||
// Create a new block out of the leftovers
|
||||
SmallHeapBlock* leftoverBlock = (SmallHeapBlock *)((char *)growBlock + newPhysicalSize);
|
||||
SmallHeapBlock* nextBlock = blockToCarve->GetNextBlock();
|
||||
|
||||
// Add the block to linked list of blocks in this raw allocation chunk.
|
||||
|
||||
nextBlock->SetPrevBlock(leftoverBlock);
|
||||
growBlock->SetBlockSize(newAllocSize);
|
||||
leftoverBlock->SetPrevBlock(growBlock);
|
||||
leftoverBlock->SetBlockSize(leftovers - SmallHeapBlock::kBlockOverhead);
|
||||
|
||||
// And add the block to a free list, which will either be
|
||||
// one of the sized bins or the overflow list, depending
|
||||
// on its size.
|
||||
|
||||
AddBlockToFreeList(leftoverBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
SmallHeapBlock* nextBlock = blockToCarve->GetNextBlock();
|
||||
nextBlock->SetPrevBlock(growBlock);
|
||||
// If we're using the entire free block, then because growBlock->blockSize
|
||||
// is used to calculate the start of the next block, it must be
|
||||
// adjusted so that still does this.
|
||||
growBlock->SetBlockSize(growBlock->GetBlockSize() + blockToCarvePhysicalSize);
|
||||
}
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
growBlock->SetPaddingBytes(newAllocSize - newSize);
|
||||
growBlock->FillPaddingBytes();
|
||||
growBlock->SetTrailerTag(growBlock->GetBlockSize(), kUsedBlockTrailerTag);
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
GetOwningAllocator()->AccountForResizedBlock(growBlock->GetLogicalBlockSize(), newSize);
|
||||
growBlock->SetLogicalBlockSize(newSize);
|
||||
#endif
|
||||
|
||||
return (void *)(&growBlock->memory);
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void *nsSmallHeapChunk::ShrinkBlock(SmallHeapBlock *shrinkBlock, size_t newSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
UInt32 newAllocSize = (newSize + 3) & ~3;
|
||||
UInt32 oldSize = shrinkBlock->GetBlockSize();
|
||||
UInt32 oldPhysicalSize = shrinkBlock->GetBlockHeapUsage();
|
||||
UInt32 newPhysicalSize = SmallHeapBlock::kBlockOverhead + newAllocSize;
|
||||
|
||||
SInt32 leftovers = (SInt32)oldPhysicalSize - newPhysicalSize;
|
||||
|
||||
MEM_ASSERT(leftovers > 0, "Should have some leftovers here");
|
||||
|
||||
SmallHeapBlock *nextBlock = shrinkBlock->GetNextBlock();
|
||||
|
||||
if (! nextBlock->IsBlockUsed())
|
||||
{
|
||||
// coalesce
|
||||
leftovers += nextBlock->GetBlockHeapUsage(); // augmented leftovers.
|
||||
RemoveBlockFromFreeList(nextBlock);
|
||||
nextBlock = nextBlock->GetNextBlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
// enough space to turn into a free block?
|
||||
if (leftovers < SmallHeapBlock::kBlockOverhead + kDefaultSmallHeadMinSize)
|
||||
return (void *)(&shrinkBlock->memory);
|
||||
}
|
||||
|
||||
// Create a new block out of the leftovers (or augmented leftovers)
|
||||
SmallHeapBlock *leftoverBlock = (SmallHeapBlock *)((char *)shrinkBlock + newPhysicalSize);
|
||||
|
||||
// Add the block to linked list of blocks in this raw
|
||||
// allocation chunk.
|
||||
|
||||
nextBlock->SetPrevBlock(leftoverBlock);
|
||||
shrinkBlock->SetBlockSize(newAllocSize);
|
||||
leftoverBlock->SetPrevBlock(shrinkBlock);
|
||||
leftoverBlock->SetBlockSize(leftovers - SmallHeapBlock::kBlockOverhead);
|
||||
|
||||
// And add the block to a free list, which will either be
|
||||
// one of the sized bins or the overflow list, depending
|
||||
// on its size.
|
||||
|
||||
AddBlockToFreeList(leftoverBlock);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
shrinkBlock->SetPaddingBytes(newAllocSize - newSize);
|
||||
shrinkBlock->FillPaddingBytes();
|
||||
shrinkBlock->SetTrailerTag(shrinkBlock->GetBlockSize(), kUsedBlockTrailerTag);
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
GetOwningAllocator()->AccountForResizedBlock(shrinkBlock->GetLogicalBlockSize(), newSize);
|
||||
shrinkBlock->SetLogicalBlockSize(newSize);
|
||||
#endif
|
||||
|
||||
return (void *)(&shrinkBlock->memory);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void* nsSmallHeapChunk::ResizeBlockInPlace(SmallHeapBlock *theBlock, size_t newSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
UInt32 newAllocSize = (newSize + 3) & ~3;
|
||||
|
||||
theBlock->SetPaddingBytes(newAllocSize - newSize);
|
||||
theBlock->FillPaddingBytes();
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
GetOwningAllocator()->AccountForResizedBlock(theBlock->GetLogicalBlockSize(), newSize);
|
||||
theBlock->SetLogicalBlockSize(newSize);
|
||||
#endif
|
||||
|
||||
return (void *)(&theBlock->memory);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsSmallHeapChunk::ReturnBlock(SmallHeapBlock *deadBlock)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
SmallHeapBlock *nextBlock = deadBlock->GetNextBlock();
|
||||
SmallHeapBlock *prevBlock = deadBlock->GetPrevBlock();
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
GetOwningAllocator()->AccountForFreedBlock(deadBlock->GetLogicalBlockSize());
|
||||
#endif
|
||||
|
||||
// If the block after us is free, then coalesce with it.
|
||||
if (! nextBlock->IsBlockUsed())
|
||||
{
|
||||
RemoveBlockFromFreeList(nextBlock);
|
||||
deadBlock->SetBlockSize( deadBlock->GetBlockSize() + nextBlock->GetBlockHeapUsage());
|
||||
nextBlock = nextBlock->GetNextBlock();
|
||||
}
|
||||
|
||||
// If the block before us is free, then coalesce with it.
|
||||
if (! prevBlock->IsBlockUsed())
|
||||
{
|
||||
RemoveBlockFromFreeList(prevBlock);
|
||||
prevBlock->SetBlockSize( ((Ptr)nextBlock - (Ptr)prevBlock) - SmallHeapBlock::kBlockOverhead);
|
||||
AddBlockToFreeList(prevBlock);
|
||||
deadBlock = prevBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddBlockToFreeList(deadBlock);
|
||||
}
|
||||
|
||||
nextBlock->SetPrevBlock(deadBlock);
|
||||
|
||||
DecrementUsedBlocks();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsSmallHeapChunk::RemoveBlockFromFreeList(SmallHeapBlock *removeBlock)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
UInt32 blockSize = removeBlock->GetBlockSize();
|
||||
|
||||
SmallHeapBlock *nextFree = removeBlock->GetNextFree();
|
||||
SmallHeapBlock *prevFree = removeBlock->GetPrevFree();
|
||||
|
||||
if (nextFree != nil)
|
||||
nextFree->SetPrevFree(prevFree);
|
||||
if (prevFree != nil)
|
||||
prevFree->SetNextFree(nextFree);
|
||||
else
|
||||
{
|
||||
if (blockSize > kMaximumBinBlockSize)
|
||||
mOverflow = nextFree;
|
||||
else
|
||||
{
|
||||
UInt32 nextBlockBin = (blockSize - kDefaultSmallHeadMinSize) >> 2;
|
||||
|
||||
MEM_ASSERT(blockSize >= kDefaultSmallHeadMinSize, "Bad block size");
|
||||
MEM_ASSERT(nextBlockBin < kDefaultSmallHeapBins, "Bad bin index");
|
||||
|
||||
mBins[nextBlockBin] = nextFree;
|
||||
}
|
||||
}
|
||||
|
||||
removeBlock->SetBlockUsed();
|
||||
mTotalFree -= removeBlock->GetBlockHeapUsage();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsSmallHeapChunk::AddBlockToFreeList(SmallHeapBlock *addBlock)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
mTotalFree += addBlock->GetBlockHeapUsage();
|
||||
|
||||
addBlock->SetBlockUnused();
|
||||
|
||||
UInt32 blockSize = addBlock->GetBlockSize();
|
||||
|
||||
addBlock->SetPrevFree(nil);
|
||||
|
||||
if (blockSize > kMaximumBinBlockSize)
|
||||
{
|
||||
SmallHeapBlock *tempBlock = mOverflow;
|
||||
addBlock->SetNextFree(tempBlock);
|
||||
if (tempBlock) tempBlock->SetPrevFree(addBlock);
|
||||
mOverflow = addBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 nextBlockBin = (blockSize - kDefaultSmallHeadMinSize) >> 2;
|
||||
|
||||
MEM_ASSERT(blockSize >= kDefaultSmallHeadMinSize, "Bad block size");
|
||||
MEM_ASSERT(nextBlockBin < kDefaultSmallHeapBins, "Bad bin index");
|
||||
|
||||
SmallHeapBlock *tempBlock = mBins[nextBlockBin];
|
||||
addBlock->SetNextFree(tempBlock);
|
||||
if (tempBlock) tempBlock->SetPrevFree(addBlock);
|
||||
mBins[nextBlockBin] = addBlock;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,221 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
class nsMemAllocator;
|
||||
class nsSmallHeapChunk;
|
||||
|
||||
|
||||
struct SmallHeapBlock
|
||||
{
|
||||
|
||||
enum {
|
||||
kBlockPaddingBytes = 'ðððð',
|
||||
kBlockInUseFlag = 0x8000,
|
||||
kBlockPaddingMask = 0x0003
|
||||
};
|
||||
|
||||
static const UInt32 kBlockOverhead;
|
||||
|
||||
static SmallHeapBlock* GetBlockHeader(void *block) { return (SmallHeapBlock *)((char *)block - sizeof(SmallHeapBlock)); }
|
||||
|
||||
SmallHeapBlock* GetNextBlock() { return (SmallHeapBlock *)((UInt32)this + GetBlockHeapUsage()); }
|
||||
SmallHeapBlock* GetPrevBlock() { return prevBlock; }
|
||||
|
||||
void SetPrevBlock(SmallHeapBlock *prev) { prevBlock = prev; }
|
||||
void SetBlockSize(UInt32 inBlockSize) { blockSize = inBlockSize; }
|
||||
|
||||
UInt32 GetBlockSize() { return blockSize; }
|
||||
UInt32 GetBlockHeapUsage() { return (GetBlockSize() + kBlockOverhead); }
|
||||
|
||||
Boolean IsBlockUsed() { return (blockFlags & kBlockInUseFlag) != 0; }
|
||||
|
||||
void SetBlockUsed() { blockFlags = 0; blockFlags |= kBlockInUseFlag; }
|
||||
void SetBlockUnused() { blockFlags &= ~kBlockInUseFlag; }
|
||||
|
||||
void SetNextFree(SmallHeapBlock *next) { info.freeInfo.nextFree = next; }
|
||||
void SetPrevFree(SmallHeapBlock *prev) { info.freeInfo.prevFree = prev; }
|
||||
|
||||
SmallHeapBlock* GetNextFree() { return info.freeInfo.nextFree; }
|
||||
SmallHeapBlock* GetPrevFree() { return info.freeInfo.prevFree; }
|
||||
|
||||
|
||||
void SetOwningChunk(nsHeapChunk *inOwningChunk) { info.inUseInfo.freeProc.owningChunk = inOwningChunk; }
|
||||
nsSmallHeapChunk* GetOwningChunk() { return (nsSmallHeapChunk *)info.inUseInfo.freeProc.owningChunk; }
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
void SetPaddingBytes(UInt32 padding) { blockFlags &= ~kBlockPaddingMask; blockFlags |= padding; }
|
||||
void FillPaddingBytes() {
|
||||
UInt32 padding = blockFlags & kBlockPaddingMask;
|
||||
long *lastLong = (long *)((char *)&memory + blockSize - sizeof(long));
|
||||
UInt32 mask = (1 << (8 * padding)) - 1;
|
||||
*lastLong &= ~mask;
|
||||
*lastLong |= (mask & kBlockPaddingBytes);
|
||||
}
|
||||
|
||||
Boolean CheckPaddingBytes() {
|
||||
UInt32 padding = blockFlags & kBlockPaddingMask;
|
||||
long *lastLong = (long *)((char *)&memory + blockSize - sizeof(long));
|
||||
UInt32 mask = (1 << (8 * padding)) - 1;
|
||||
return (*lastLong & mask) == (mask & kBlockPaddingBytes);
|
||||
}
|
||||
|
||||
UInt32 GetPaddingBytes() { return (blockFlags & kBlockPaddingMask); }
|
||||
|
||||
void ZapBlockContents(UInt8 pattern) { memset(&memory, pattern, blockSize); }
|
||||
|
||||
// inline, so won't crash if this is a bad block
|
||||
Boolean HasHeaderTag(MemoryBlockTag inHeaderTag)
|
||||
{ return info.inUseInfo.freeProc.headerTag == inHeaderTag; }
|
||||
|
||||
void SetHeaderTag(MemoryBlockTag inHeaderTag)
|
||||
{ info.inUseInfo.freeProc.headerTag = inHeaderTag; }
|
||||
|
||||
void SetTrailerTag(UInt32 blockSize, MemoryBlockTag theTag)
|
||||
{
|
||||
MemoryBlockTrailer *trailer = (MemoryBlockTrailer *)((char *)&memory + blockSize);
|
||||
trailer->trailerTag = theTag;
|
||||
}
|
||||
Boolean HasTrailerTag(UInt32 blockSize, MemoryBlockTag theTag)
|
||||
{
|
||||
MemoryBlockTrailer *trailer = (MemoryBlockTrailer *)((char *)&memory + blockSize);
|
||||
return (trailer->trailerTag == theTag);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
size_t GetLogicalBlockSize() { return info.inUseInfo.freeProc.logicalBlockSize; }
|
||||
void SetLogicalBlockSize(size_t blockSize) { info.inUseInfo.freeProc.logicalBlockSize = blockSize; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
SmallHeapBlock *prevBlock;
|
||||
UInt16 blockFlags; // the top bit is the in use flag, the bottom 3 bits padding bytes
|
||||
UInt16 blockSize;
|
||||
union {
|
||||
struct {
|
||||
SmallHeapBlock *nextFree;
|
||||
SmallHeapBlock *prevFree;
|
||||
} freeInfo;
|
||||
struct {
|
||||
UInt32 filler;
|
||||
MemoryBlockHeader freeProc; // this must be the last variable before memory
|
||||
} inUseInfo;
|
||||
} info;
|
||||
|
||||
public:
|
||||
char memory[];
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class nsSmallHeapAllocator : public nsMemAllocator
|
||||
{
|
||||
friend class nsSmallHeapChunk;
|
||||
|
||||
private:
|
||||
|
||||
typedef nsMemAllocator Inherited;
|
||||
|
||||
public:
|
||||
|
||||
nsSmallHeapAllocator(size_t minBlockSize, size_t maxBlockSize);
|
||||
~nsSmallHeapAllocator();
|
||||
|
||||
void * AllocatorMakeBlock(size_t blockSize);
|
||||
void AllocatorFreeBlock(void *freeBlock);
|
||||
void * AllocatorResizeBlock(void *block, size_t newSize);
|
||||
size_t AllocatorGetBlockSize(void *thisBlock);
|
||||
|
||||
nsHeapChunk* AllocateChunk(size_t blockSize);
|
||||
void FreeChunk(nsHeapChunk *chunkToFree);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
nsSmallHeapChunk* mChunkWithSpace; // cheap optimization
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class nsSmallHeapChunk : public nsHeapChunk
|
||||
{
|
||||
public:
|
||||
|
||||
nsSmallHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize);
|
||||
~nsSmallHeapChunk();
|
||||
|
||||
void * GetSpaceForBlock(UInt32 roundedBlockSize);
|
||||
void ReturnBlock(SmallHeapBlock *deadBlock);
|
||||
|
||||
void * GrowBlock(SmallHeapBlock *growBlock, size_t newSize);
|
||||
void * ShrinkBlock(SmallHeapBlock *shrinkBlock, size_t newSize);
|
||||
void * ResizeBlockInPlace(SmallHeapBlock *shrinkBlock, size_t newSize);
|
||||
|
||||
protected:
|
||||
|
||||
enum {
|
||||
kDefaultSmallHeadMinSize = 4L,
|
||||
kDefaultSmallHeapBins = 128L,
|
||||
kMaximumBinBlockSize = kDefaultSmallHeadMinSize + 4L * kDefaultSmallHeapBins - 1,
|
||||
kMaximumBlockSize = 0xFFFF
|
||||
};
|
||||
|
||||
SmallHeapBlock** GetBins(UInt32 binIndex)
|
||||
{
|
||||
MEM_ASSERT(binIndex < kDefaultSmallHeapBins, "Bad bin index!");
|
||||
return mBins + binIndex;
|
||||
}
|
||||
|
||||
SmallHeapBlock* GetOverflow() { return mOverflow; }
|
||||
|
||||
void RemoveBlockFromFreeList(SmallHeapBlock *removeBlock);
|
||||
void AddBlockToFreeList(SmallHeapBlock *addBlock);
|
||||
|
||||
UInt32 mTotalFree;
|
||||
#if DEBUG
|
||||
UInt32 mInitialFree;
|
||||
#endif
|
||||
SmallHeapBlock* mOverflow;
|
||||
SmallHeapBlock* mBins[kDefaultSmallHeapBins];
|
||||
SmallHeapBlock mMemory[];
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -1,431 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
/*
|
||||
A set of classes for giving the memory allocators a thorough workout.
|
||||
|
||||
CMemoryBlock
|
||||
This class manages a single memory block, which is allocated with
|
||||
malloc(). The block is filled with a patter, and tag words put at
|
||||
each end. The various operators allow you to change the block size;
|
||||
for each change, the block is realloc'd and the tag words replaced.
|
||||
Before each operation, the block contents are checked to ensure that
|
||||
no-one wrote over them.
|
||||
|
||||
CMemoryTester
|
||||
This class manages an array of CMemoryBlocks. In DoMemoryTesting(), it
|
||||
allocates about 200 block with random sizes in a wide range, then
|
||||
makes them bigger, smaller, frees some, allocates some more, and resizes
|
||||
them again.
|
||||
|
||||
Its destructor frees the blocks.
|
||||
|
||||
CMemoryTesterPeriodical
|
||||
This is a periodical that runs the memory tests. In the current implementaion,
|
||||
it manages an array of CMemoryTesters. On each idle, it allocates a new
|
||||
CMemoryTester, and does the testing. That CMemoryTester is put in an
|
||||
array to keep track of it (but the memory is not freed yet). So on every
|
||||
idle it "leaks" all the blocks managed by the tester. Memory soon gets
|
||||
used up.
|
||||
|
||||
At some point an allocation will fail, and CMemoryBlock throws an exception.
|
||||
This is caught by the CMemoryTesterPeriodical, which then frees up all the
|
||||
CMemoryTesters. Next time around, it all starts again.
|
||||
|
||||
How to use:
|
||||
|
||||
Hook up your periodical in a convenient place like CFrontApp::Initialize():
|
||||
CMemoryTesterPeriodical *tester = new CMemoryTesterPeriodical();
|
||||
tester->StartIdling();
|
||||
|
||||
The app starts to run real slow, and if you watch memory use in the Finder,
|
||||
you will see it fluctuate wildly as the periodical leaks lots of memory,
|
||||
frees it all, then leaks it again. Since this is running on a periodical,
|
||||
you can be browsing the web at the same time, albeit slowly.
|
||||
|
||||
If any errors are detected (e.g. the block tags have been overwritten),
|
||||
then you will assert.
|
||||
|
||||
*/
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <LArrayIterator.h>
|
||||
|
||||
#include "CMemoryWorkout.h"
|
||||
|
||||
#define kMinSize 8
|
||||
|
||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
CMemoryBlock::CMemoryBlock()
|
||||
: mBlockData(NULL)
|
||||
, mBlockSize(0)
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
CMemoryBlock::CMemoryBlock(UInt32 inBlockSize)
|
||||
: mBlockSize(inBlockSize)
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
if (mBlockSize < kMinSize)
|
||||
mBlockSize = kMinSize;
|
||||
mBlockData = (char *)malloc(mBlockSize);
|
||||
ThrowIfNil_(mBlockData);
|
||||
|
||||
InsertCheckBlocks();
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
CMemoryBlock::~CMemoryBlock()
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
if (GetBlockData())
|
||||
{
|
||||
Boolean isGood = QuickCheckBlock();
|
||||
Assert_(isGood);
|
||||
}
|
||||
|
||||
free(mBlockData);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
long *CMemoryBlock::GetBlockStartPtr()
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
return (long *)mBlockData;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
long *CMemoryBlock::GetBlockEndPtr()
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
if (!mBlockData) return nil;
|
||||
|
||||
char *dataEnd = mBlockData + mBlockSize;
|
||||
return (long *)(dataEnd - sizeof(long));
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
Boolean CMemoryBlock::QuickCheckBlock()
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
ThrowIfNil_(mBlockData);
|
||||
|
||||
long *startCheckPtr = GetBlockStartPtr();
|
||||
long *endCheckPtr = GetBlockEndPtr();
|
||||
|
||||
return (*startCheckPtr == eBlockStartMarker && *endCheckPtr == eBlockEndMarker);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
Boolean CMemoryBlock::ThoroughCheckBlock()
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
if (!QuickCheckBlock())
|
||||
return false;
|
||||
|
||||
return true; // I'm too lazy to do the whole thing
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
void CMemoryBlock::InsertCheckBlocks()
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
ThrowIfNil_(mBlockData);
|
||||
|
||||
memset(mBlockData, eBlockFillPattern, mBlockSize);
|
||||
|
||||
long *startCheckPtr = GetBlockStartPtr();
|
||||
long *endCheckPtr = GetBlockEndPtr();
|
||||
|
||||
*startCheckPtr = eBlockStartMarker;
|
||||
*endCheckPtr = eBlockEndMarker;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
void CMemoryBlock::ChangeBlockSize(UInt32 newSize)
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
ThrowIfNil_(mBlockData);
|
||||
|
||||
Assert_(QuickCheckBlock());
|
||||
|
||||
mBlockSize = MAX(newSize, kMinSize);
|
||||
mBlockData = (char *)realloc((void *)mBlockData, mBlockSize);
|
||||
|
||||
ThrowIfNil_(mBlockData);
|
||||
|
||||
InsertCheckBlocks();
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
void CMemoryBlock::operator++(int)
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
ChangeBlockSize(mBlockSize + 1);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
void CMemoryBlock::operator--(int)
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
ChangeBlockSize(mBlockSize - 1);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
void CMemoryBlock::operator+=(UInt32 incSize)
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
ChangeBlockSize(mBlockSize + incSize);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
void CMemoryBlock::operator-=(UInt32 decSize)
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
if (decSize > mBlockSize)
|
||||
decSize = 0;
|
||||
UInt32 newSize = mBlockSize - decSize;
|
||||
ChangeBlockSize(newSize > kMinSize ? newSize : kMinSize);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
CMemoryTester::CMemoryTester()
|
||||
: mBlocksArray(sizeof(CMemoryBlock *))
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
CMemoryTester::~CMemoryTester()
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
LArrayIterator iter(mBlocksArray);
|
||||
CMemoryBlock *theBlock;
|
||||
|
||||
while (iter.Next(&theBlock) && theBlock)
|
||||
{
|
||||
delete theBlock;
|
||||
}
|
||||
|
||||
mBlocksArray.RemoveItemsAt(mBlocksArray.GetCount(), LArray::index_First);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
void CMemoryTester::DoMemoryTesting()
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
// let's make some objects with random sizes
|
||||
|
||||
for (Int32 i = 0; i < 10; i ++)
|
||||
{
|
||||
CMemoryBlock *newBlock = new CMemoryBlock( 1024 * (::Random() & 0x05FF) + (::Random() & 0x7FFF));
|
||||
|
||||
mBlocksArray.InsertItemsAt(1, LArray::index_Last, &newBlock);
|
||||
}
|
||||
|
||||
for (Int32 i = 0; i < 100; i ++)
|
||||
{
|
||||
CMemoryBlock *newBlock = new CMemoryBlock( 1024 * (::Random() & 0x07F) + (::Random() & 0x7FFF));
|
||||
|
||||
mBlocksArray.InsertItemsAt(1, LArray::index_Last, &newBlock);
|
||||
}
|
||||
|
||||
for (Int32 i = 0; i < 3000; i ++)
|
||||
{
|
||||
CMemoryBlock *newBlock = new CMemoryBlock(::Random() & 0x009F);
|
||||
|
||||
mBlocksArray.InsertItemsAt(1, LArray::index_Last, &newBlock);
|
||||
}
|
||||
|
||||
|
||||
/* now let's resize them
|
||||
LArrayIterator iter(mBlocksArray);
|
||||
CMemoryBlock *theBlock;
|
||||
while (iter.Next(&theBlock) && theBlock)
|
||||
{
|
||||
(*theBlock)++;
|
||||
}
|
||||
|
||||
iter.ResetTo(LArrayIterator::index_BeforeStart);
|
||||
while (iter.Next(&theBlock) && theBlock)
|
||||
{
|
||||
(*theBlock)++;
|
||||
}
|
||||
|
||||
iter.ResetTo(LArrayIterator::index_BeforeStart);
|
||||
while (iter.Next(&theBlock) && theBlock)
|
||||
{
|
||||
(*theBlock)++;
|
||||
}
|
||||
|
||||
iter.ResetTo(LArrayIterator::index_BeforeStart);
|
||||
while (iter.Next(&theBlock) && theBlock)
|
||||
{
|
||||
(*theBlock) -= 10;
|
||||
}
|
||||
|
||||
iter.ResetTo(LArrayIterator::index_BeforeStart);
|
||||
while (iter.Next(&theBlock) && theBlock)
|
||||
{
|
||||
(*theBlock) += (::Random() & 0x07FF);
|
||||
}
|
||||
|
||||
iter.ResetTo(LArrayIterator::index_BeforeStart);
|
||||
while (iter.Next(&theBlock) && theBlock)
|
||||
{
|
||||
(*theBlock) += 0; // resize to same size
|
||||
}
|
||||
|
||||
|
||||
// now let's free every other block, and then reallocate them
|
||||
iter.ResetTo(LArrayIterator::index_BeforeStart);
|
||||
ArrayIndexT n = LArray::index_First;
|
||||
|
||||
while (iter.Next(&theBlock) && theBlock)
|
||||
{
|
||||
if ((n & 1) == 0)
|
||||
{
|
||||
delete theBlock;
|
||||
|
||||
theBlock = new CMemoryBlock(::Random() & 0x09F);
|
||||
|
||||
mBlocksArray.AssignItemsAt(1, n, &theBlock);
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
// now let's free every other block, and then reallocate them
|
||||
iter.ResetTo(LArrayIterator::index_BeforeStart);
|
||||
n = LArray::index_First;
|
||||
|
||||
while (iter.Next(&theBlock) && theBlock)
|
||||
{
|
||||
if ((n & 1) == 1)
|
||||
{
|
||||
delete theBlock;
|
||||
|
||||
theBlock = new CMemoryBlock(::Random() & 0x09F);
|
||||
|
||||
mBlocksArray.AssignItemsAt(1, n, &theBlock);
|
||||
}
|
||||
n++;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
iter.ResetTo(LArrayIterator::index_BeforeStart);
|
||||
while (iter.Next(&theBlock) && theBlock)
|
||||
{
|
||||
(*theBlock) -= (::Random() & 0x07FF);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
CMemoryTesterPeriodical::CMemoryTesterPeriodical()
|
||||
: LPeriodical()
|
||||
, mTestersArray(sizeof(CMemoryTester *))
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
CMemoryTesterPeriodical::~CMemoryTesterPeriodical()
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
FreeTesters();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
void CMemoryTesterPeriodical::FreeTesters()
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
LArrayIterator iter(mTestersArray);
|
||||
CMemoryTester *theTester;
|
||||
|
||||
while (iter.Next(&theTester) && theTester)
|
||||
{
|
||||
delete theTester;
|
||||
}
|
||||
|
||||
mTestersArray.RemoveItemsAt(mTestersArray.GetCount(), LArray::index_First);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
void CMemoryTesterPeriodical::SpendTime(const EventRecord & /*inMacEvent */)
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
try
|
||||
{
|
||||
CMemoryTester *tester = new CMemoryTester();
|
||||
|
||||
mTestersArray.InsertItemsAt(1, LArray::index_Last, &tester);
|
||||
|
||||
tester->DoMemoryTesting();
|
||||
// leak the damn thing
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
DebugStr("\pWe ran out of memory. Free up time.");
|
||||
FreeTesters();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
/*
|
||||
CMemoryWorkout.h
|
||||
|
||||
See the .cp file for an explanation of what this stuff does.
|
||||
|
||||
*/
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <LPeriodical.h>
|
||||
#include <LArray.h>
|
||||
|
||||
class CMemoryBlock
|
||||
{
|
||||
private:
|
||||
|
||||
enum
|
||||
{
|
||||
eBlockStartMarker = 'SMFR',
|
||||
eBlockEndMarker = 'smfr'
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
eBlockFillPattern = '0xBA'
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
CMemoryBlock();
|
||||
CMemoryBlock(UInt32 inBlockSize);
|
||||
|
||||
~CMemoryBlock();
|
||||
|
||||
Boolean QuickCheckBlock();
|
||||
Boolean ThoroughCheckBlock();
|
||||
|
||||
void operator++(int);
|
||||
void operator--(int);
|
||||
void operator+=(UInt32 incSize);
|
||||
void operator-=(UInt32 decSize);
|
||||
|
||||
protected:
|
||||
|
||||
char *GetBlockData() { return mBlockData; }
|
||||
UInt32 GetBlockSize() { return mBlockSize; }
|
||||
|
||||
void ChangeBlockSize(UInt32 newSize);
|
||||
void InsertCheckBlocks();
|
||||
|
||||
long *GetBlockStartPtr();
|
||||
long *GetBlockEndPtr();
|
||||
|
||||
char *mBlockData;
|
||||
UInt32 mBlockSize;
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class CMemoryTester
|
||||
{
|
||||
public:
|
||||
CMemoryTester();
|
||||
~CMemoryTester();
|
||||
|
||||
void DoMemoryTesting();
|
||||
|
||||
protected:
|
||||
|
||||
LArray mBlocksArray;
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
class CMemoryTesterPeriodical : public LPeriodical
|
||||
{
|
||||
public:
|
||||
CMemoryTesterPeriodical();
|
||||
~CMemoryTesterPeriodical();
|
||||
|
||||
virtual void SpendTime(const EventRecord &inMacEvent);
|
||||
|
||||
private:
|
||||
|
||||
void FreeTesters();
|
||||
|
||||
LArray mTestersArray;
|
||||
};
|
|
@ -1,89 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
#if __profile__
|
||||
#include <Profiler.h>
|
||||
#include <Processes.h>
|
||||
#endif
|
||||
|
||||
#include "CMemoryWorkout.h"
|
||||
|
||||
void main(void)
|
||||
{
|
||||
|
||||
#if __profile__
|
||||
if (ProfilerInit(collectDetailed, bestTimeBase, 500, 20) != noErr)
|
||||
ExitToShell();
|
||||
#endif
|
||||
|
||||
// if you comment out the std::cout << calls below for profiling
|
||||
// reasons, you need to called InitGraf because I use Random()
|
||||
|
||||
//::InitGraf(&qd.thePort);
|
||||
|
||||
std::cout << "Starting up";
|
||||
|
||||
CMemoryTester *tester = new CMemoryTester;
|
||||
|
||||
for (UInt32 i = 0; i < 1; i ++)
|
||||
{
|
||||
|
||||
std::cout << i << std::endl;
|
||||
|
||||
try
|
||||
{
|
||||
tester->DoMemoryTesting();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
std::cout << "Caught exception";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
delete tester;
|
||||
|
||||
#if __profile__
|
||||
ProfilerDump("\pMemoryTester.prof");
|
||||
ProfilerTerm();
|
||||
#endif
|
||||
}
|
||||
|
Двоичные данные
lib/mac/MacMemoryAllocator/test/MemoryTest.mcp
Двоичные данные
lib/mac/MacMemoryAllocator/test/MemoryTest.mcp
Двоичный файл не отображается.
|
@ -1,76 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#ifndef _MoreMixedMode_
|
||||
#define _MoreMixedMode_
|
||||
|
||||
/*
|
||||
In a .h file, global (procedure declaration):
|
||||
extern RoutineDescriptor foo_info;
|
||||
PROCDECL(extern,foo);
|
||||
|
||||
In the .h file, class scoped (member declaration):
|
||||
static RoutineDescriptor foo_info;
|
||||
PROCDECL(static,foo);
|
||||
|
||||
In the .cp file, global (procedure definition):
|
||||
RoutineDescriptor foo_info = RoutineDescriptor (foo);
|
||||
PROCEDURE(foo,uppFooType);
|
||||
|
||||
In the .cp file, class scoped (member definition):
|
||||
RoutineDescriptor Foo::foo_info = RoutineDescriptor (Bar::foo);
|
||||
PROCDEF(Foo::,Bar::,foo,uppFooType);
|
||||
|
||||
References to the function:
|
||||
foo_info
|
||||
PROCPTR(foo)
|
||||
*/
|
||||
|
||||
#include "MixedMode.h"
|
||||
#if GENERATINGCFM
|
||||
# define PROCPTR(NAME) NAME##_info
|
||||
# define PROCDECL(MOD,NAME) MOD RoutineDescriptor PROCPTR(NAME);
|
||||
# define PROCDEF(S1,S2,NAME,INFO) RoutineDescriptor S1##PROCPTR(NAME) = BUILD_ROUTINE_DESCRIPTOR (INFO, S2##NAME);
|
||||
# define PROCEDURE(NAME,INFO) RoutineDescriptor PROCPTR(NAME) = BUILD_ROUTINE_DESCRIPTOR (INFO, NAME);
|
||||
#else
|
||||
# define PROCPTR(NAME) NAME
|
||||
# define PROCDECL(MOD,NAME)
|
||||
# define PROCDEF(S1,S2,NAME,INFO)
|
||||
# define PROCEDURE(NAME,INFO)
|
||||
#endif
|
||||
|
||||
#endif // _MoreMixedMode_
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#pragma once
|
||||
#include <stdlib.h>
|
||||
#include "prtypes.h"
|
||||
|
||||
typedef enum MemoryPriority { fcNone, fcLow, fcMedium, fcHigh, fcTop } MemoryPriority;
|
||||
|
||||
#define NEW( CLASS ) ( new CLASS )
|
||||
#define DELETE( OBJECT ) delete OBJECT
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
extern void* Flush_Allocate( size_t size, int zero );
|
||||
extern void* Flush_Reallocate( void* item, size_t size );
|
||||
extern void Flush_Free( void* item );
|
||||
|
||||
PR_END_EXTERN_C
|
|
@ -1,243 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#ifdef mktime
|
||||
#undef mktime
|
||||
#undef ctime
|
||||
#undef localtime
|
||||
_C_LIB_DECL /* declarations */
|
||||
time_t mktime(struct tm *);
|
||||
char *ctime(const time_t *);
|
||||
struct tm *localtime(const time_t *);
|
||||
_END_C_LIB_DECL
|
||||
#endif
|
||||
|
||||
#ifndef UNIXMINUSMACTIME
|
||||
#define UNIXMINUSMACTIME 2082844800UL
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
#ifndef __OSUTILS__
|
||||
#include <OSUtils.h>
|
||||
#endif
|
||||
#ifndef __TOOLUTILS__
|
||||
#include <ToolUtils.h>
|
||||
#endif
|
||||
|
||||
#include "xp_mcom.h" /* prototypes for GetTimeMac, Mactime, Macmktime, Macctime, Maclocaltime, Macgmtime */
|
||||
#undef ctime
|
||||
#undef mktime
|
||||
|
||||
// Because serial port and SLIP conflict with ReadXPram calls,
|
||||
// we cache the call here
|
||||
// The symptoms are the
|
||||
void MyReadLocation(MachineLocation * loc);
|
||||
long GMTDelta();
|
||||
|
||||
|
||||
void MyReadLocation(MachineLocation * loc)
|
||||
{
|
||||
static MachineLocation storedLoc; // InsideMac, OSUtilities, page 4-20
|
||||
static Boolean didReadLocation = false;
|
||||
if (!didReadLocation)
|
||||
{
|
||||
ReadLocation(&storedLoc);
|
||||
didReadLocation = true;
|
||||
}
|
||||
*loc = storedLoc;
|
||||
}
|
||||
|
||||
#if 0
|
||||
Boolean DaylightSavings()
|
||||
{
|
||||
MachineLocation loc;
|
||||
unsigned char dlsDelta;
|
||||
MyReadLocation(&loc);
|
||||
dlsDelta = loc.u.dlsDelta;
|
||||
return (dlsDelta != 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
// This routine is copied straight out of stdio sources.
|
||||
// The only difference is that we use MyReadLocation instead of ReadLocation.
|
||||
struct tm *(gmtime)(const time_t *tod)
|
||||
{ /* convert to Greenwich Mean Time (UTC) */
|
||||
MachineLocation myLocation;
|
||||
long int internalGmtDelta;
|
||||
time_t ltime;
|
||||
MyReadLocation(&myLocation);
|
||||
internalGmtDelta = myLocation.u.gmtDelta & 0x00ffffff;
|
||||
if (internalGmtDelta & 0x00800000)
|
||||
internalGmtDelta = internalGmtDelta | 0xff000000;
|
||||
ltime = (*tod) - internalGmtDelta;
|
||||
return (localtime(&(ltime)));
|
||||
}
|
||||
|
||||
|
||||
// We need to do this, because we wrap localtime as a macro in
|
||||
#ifdef localtime
|
||||
#undef localtime
|
||||
#endif
|
||||
struct tm *localtime(const time_t *tp)
|
||||
{
|
||||
DateTimeRec dtr;
|
||||
MachineLocation loc;
|
||||
static struct tm statictime;
|
||||
static const short monthday[12] =
|
||||
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
|
||||
|
||||
SecondsToDate(*tp, &dtr);
|
||||
statictime.tm_sec = dtr.second;
|
||||
statictime.tm_min = dtr.minute;
|
||||
statictime.tm_hour = dtr.hour;
|
||||
statictime.tm_mday = dtr.day;
|
||||
statictime.tm_mon = dtr.month - 1;
|
||||
statictime.tm_year = dtr.year - 1900;
|
||||
statictime.tm_wday = dtr.dayOfWeek - 1;
|
||||
statictime.tm_yday = monthday[statictime.tm_mon]
|
||||
+ statictime.tm_mday - 1;
|
||||
if (2 < statictime.tm_mon && !(statictime.tm_year & 3))
|
||||
++statictime.tm_yday;
|
||||
MyReadLocation(&loc);
|
||||
statictime.tm_isdst = loc.u.dlsDelta;
|
||||
return(&statictime);
|
||||
}
|
||||
|
||||
|
||||
// current local time = GMTDelta() + GMT
|
||||
// GMT = local time - GMTDelta()
|
||||
long GMTDelta()
|
||||
{
|
||||
MachineLocation loc;
|
||||
long gmtDelta;
|
||||
|
||||
MyReadLocation(&loc);
|
||||
gmtDelta = loc.u.gmtDelta & 0x00FFFFFF;
|
||||
if ((gmtDelta & 0x00800000) != 0)
|
||||
gmtDelta |= 0xFF000000;
|
||||
return gmtDelta;
|
||||
}
|
||||
|
||||
|
||||
// This routine simulates stdclib time(), time in seconds since 1.1.1970
|
||||
// The time is in GMT
|
||||
time_t GetTimeMac()
|
||||
{
|
||||
unsigned long maclocal;
|
||||
// Get Mac local time
|
||||
GetDateTime(&maclocal);
|
||||
// Get Mac GMT
|
||||
maclocal -= GMTDelta();
|
||||
// return unix GMT
|
||||
return (maclocal - UNIXMINUSMACTIME);
|
||||
}
|
||||
|
||||
// Returns the GMT times
|
||||
time_t Mactime(time_t *timer)
|
||||
{
|
||||
time_t t = GetTimeMac();
|
||||
if (timer != NULL)
|
||||
*timer = t;
|
||||
return t;
|
||||
}
|
||||
|
||||
time_t Macmktime (struct tm *timeptr)
|
||||
{
|
||||
time_t theTime;
|
||||
|
||||
// ¥¥¥ HACK to work around the bug in mktime
|
||||
int negativeDiff = 0;
|
||||
if (timeptr->tm_sec < 0)
|
||||
{
|
||||
negativeDiff += timeptr->tm_sec;
|
||||
timeptr->tm_sec = 0;
|
||||
}
|
||||
if (timeptr->tm_min < 0)
|
||||
{
|
||||
negativeDiff += timeptr->tm_min*60;
|
||||
timeptr->tm_min = 0;
|
||||
}
|
||||
if (timeptr->tm_hour < 0)
|
||||
{
|
||||
negativeDiff += timeptr->tm_hour*60*60;
|
||||
timeptr->tm_hour = 0;
|
||||
}
|
||||
if (timeptr->tm_mday < 0)
|
||||
{
|
||||
negativeDiff += timeptr->tm_mday*60*60*24;
|
||||
timeptr->tm_mday = 0;
|
||||
}
|
||||
|
||||
// local/Mac
|
||||
theTime = mktime(timeptr);
|
||||
// mktime does not care what the daylightsavings flag is
|
||||
timeptr->tm_isdst = 0;//DaylightSavings();
|
||||
theTime += negativeDiff;
|
||||
|
||||
// GMT/Mac
|
||||
theTime -= GMTDelta();
|
||||
// unix/GMT
|
||||
return theTime - UNIXMINUSMACTIME;
|
||||
}
|
||||
|
||||
//
|
||||
char * Macctime(const time_t * t)
|
||||
{
|
||||
// GMT Mac
|
||||
time_t macTime = *t + UNIXMINUSMACTIME;
|
||||
// local Mac
|
||||
macTime += GMTDelta();
|
||||
|
||||
return ctime(&macTime);
|
||||
}
|
||||
|
||||
struct tm *Maclocaltime(const time_t * t)
|
||||
{
|
||||
// GMT Mac
|
||||
time_t macLocal = *t + UNIXMINUSMACTIME;
|
||||
// local Mac
|
||||
macLocal += GMTDelta();
|
||||
return localtime(&macLocal);
|
||||
}
|
||||
|
||||
// -> unix GMT
|
||||
struct tm *Macgmtime (const time_t *clock)
|
||||
{
|
||||
// GMT Mac
|
||||
time_t macGMT = *clock + UNIXMINUSMACTIME;
|
||||
return localtime(&macGMT);
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#error "You should now include <strstream.h> from CWPro4"
|
||||
|
||||
#include "xp_mcom.h"
|
||||
#include <sstream.h>
|
||||
|
||||
typedef basic_ostringstream<char, char_traits<char> > template_ostrstream;
|
||||
|
||||
class ostrstream : public template_ostrstream
|
||||
{
|
||||
public:
|
||||
inline const char* str() const
|
||||
{
|
||||
string astr = template_ostrstream::str();
|
||||
const char* cstr = astr.c_str();
|
||||
return XP_STRDUP(cstr);
|
||||
};
|
||||
};
|
|
@ -1,63 +0,0 @@
|
|||
__dc_arr
|
||||
__del_arr
|
||||
__new_arr
|
||||
__init_arr
|
||||
__copy
|
||||
__vt__Q23std13bad_exception # std::bad_exception::__vt
|
||||
#__vt__Q23std9exception # std::exception::__vt
|
||||
#what__Q23std9exceptionCFv # std::exception::what() const
|
||||
#__ct__Q23std9exceptionFv # std::exception::exception()
|
||||
#__dt__Q23std9exceptionFv # std::exception::~exception()
|
||||
what__Q23std13bad_exceptionCFv # std::bad_exception::what() const
|
||||
__end__catch
|
||||
__throw
|
||||
__unexpected
|
||||
__dt__Q23std13bad_exceptionFv # std::bad_exception::~bad_exception()
|
||||
__unregister_fragment
|
||||
__register_fragment
|
||||
__global_destructor_chain
|
||||
__destroy_global_chain
|
||||
__register_global_object
|
||||
__register_atexit
|
||||
__destroy_new_array2
|
||||
__destroy_new_array
|
||||
__destroy_arr
|
||||
__construct_array
|
||||
__dt__26__partial_array_destructorFv # __partial_array_destructor::~__partial_array_destructor()
|
||||
__construct_new_array
|
||||
__throw_catch_compare
|
||||
unexpected__3stdFv # std::unexpected()
|
||||
set_unexpected__3stdFPFv_v # std::set_unexpected(void (*)(void))
|
||||
terminate__3stdFv # std::terminate()
|
||||
set_terminate__3stdFPFv_v # std::set_terminate(void (*)(void))
|
||||
#__vt__Q23std8bad_cast # std::bad_cast::__vt
|
||||
__vt__Q23std10bad_typeid # std::bad_typeid::__vt
|
||||
what__Q23std10bad_typeidCFv # std::bad_typeid::what() const
|
||||
#what__Q23std8bad_castCFv # std::bad_cast::what() const
|
||||
__dynamic_cast
|
||||
#__dt__Q23std8bad_castFv # std::bad_cast::~bad_cast()
|
||||
__get_typeid
|
||||
__dt__Q23std10bad_typeidFv # std::bad_typeid::~bad_typeid()
|
||||
nothrow__3std
|
||||
#__dla__FPv # __dla(void*)
|
||||
#__nwa__FUlRCQ23std9nothrow_t # __nwa(unsigned long,const std::nothrow_t&)
|
||||
#__nwa__FUl # __nwa(unsigned long)
|
||||
#__dl__FPv # operator delete(void*)
|
||||
#__nw__FUlRCQ23std9nothrow_t # operator new(unsigned long,const std::nothrow_t&)
|
||||
#__nw__FUl # operator new(unsigned long)
|
||||
#_prealloc_newpool__3stdFUl # std::_prealloc_newpool(unsigned long)
|
||||
#_set_newnonptrmax__3stdFUl # std::_set_newnonptrmax(unsigned long)
|
||||
#_set_newpoolsize__3stdFUl # std::_set_newpoolsize(unsigned long)
|
||||
__throws_bad_alloc__3std # std::__throws_bad_alloc
|
||||
#__vt__Q23std9bad_alloc # std::bad_alloc::__vt
|
||||
__new_handler__3std # std::__new_handler
|
||||
#what__Q23std9bad_allocCFv # std::bad_alloc::what() const
|
||||
__del_hdl
|
||||
__new_hdl
|
||||
set_new_handler__3stdFPFv_v # std::set_new_handler(void (*)(void))
|
||||
__throw_bad_alloc__3stdFv # std::__throw_bad_alloc()
|
||||
#__dt__Q23std9bad_allocFv # std::bad_alloc::~bad_alloc()
|
||||
#__ptmf_null
|
||||
#longjmp
|
||||
#__terminate
|
||||
#__initialize
|
|
@ -1,30 +0,0 @@
|
|||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
|
||||
# Build NSRuntimeStubs
|
||||
|
||||
Evaluate % = ("{{SourceFile}}" =~ /(Å:)¨0Å/)
|
||||
|
||||
MakeStub "{{SourceFile}}" -o "{{¨0}}:::dist:client_stubs:NSRuntimeStubs" ¶
|
||||
-fragname NSRuntime ¶
|
||||
-vercur 0 -verdef 0 -verimp 0
|
||||
|
||||
exit 1
|
|
@ -1,42 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "DefinesMac.h"
|
||||
#include "IDE_Options.h"
|
||||
#include "ansi_prefix.mac.h"
|
||||
|
||||
#define NEWMODE NEWMODE_NONE
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,44 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#include "DefinesMac.h"
|
||||
#include "IDE_Options.h"
|
||||
#include "ansi_prefix.mac.h"
|
||||
|
||||
#define NEWMODE NEWMODE_NONE
|
|
@ -1,2 +0,0 @@
|
|||
# only export this when _not_ building for Carbon.
|
||||
qd
|
|
@ -1,10 +0,0 @@
|
|||
#library
|
||||
__PROFILE_EXIT
|
||||
__PROFILE_ENTRY
|
||||
|
||||
#utils
|
||||
ProfileStart
|
||||
ProfileStop
|
||||
ProfileSuspend
|
||||
ProfileResume
|
||||
ProfileInProgress
|
|
@ -1,50 +0,0 @@
|
|||
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void ProfileStart();
|
||||
extern void ProfileStop();
|
||||
extern void ProfileSuspend();
|
||||
extern void ProfileResume();
|
||||
extern Boolean ProfileInProgress();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,129 +0,0 @@
|
|||
/*
|
||||
GC_profiler.cpp
|
||||
|
||||
Experimental hack to clear stack frames upon entry, to make a conservative
|
||||
garbage collector more accurate.
|
||||
*/
|
||||
|
||||
#include <Profiler.h>
|
||||
|
||||
#pragma profile off
|
||||
|
||||
/**
|
||||
* Instruction constants. To clear the stack frame accurately,
|
||||
* we "interpret" the caller's prologue to see which stack locations
|
||||
* are already in use to save non-volatile registers. this is pretty
|
||||
* specific to Metrowerks generated PowerPC code.
|
||||
*/
|
||||
const unsigned MFLR_R0 = 0x7C0802A6;
|
||||
const unsigned STW = 0x24; // 0b100100 == 0x24
|
||||
const unsigned STMW = 0x2F; // 0b101111 == 0x2F
|
||||
const unsigned R1 = 0x01;
|
||||
|
||||
/**
|
||||
* Multiplicative hash, from Knuth 6.4.
|
||||
*/
|
||||
const unsigned GOLDEN_RATIO = 0x9E3779B9U;
|
||||
|
||||
/**
|
||||
* A PowerPC store instruction has this form.
|
||||
*/
|
||||
struct store {
|
||||
unsigned opcode : 6;
|
||||
unsigned source : 5;
|
||||
unsigned destination : 5;
|
||||
signed offset : 16;
|
||||
};
|
||||
|
||||
struct stack_frame {
|
||||
stack_frame* next; // savedSP
|
||||
void* savedCR;
|
||||
void* savedLR;
|
||||
void* reserved0;
|
||||
void* reserved1;
|
||||
void* savedTOC;
|
||||
};
|
||||
|
||||
struct offset_cache {
|
||||
void* savedLR;
|
||||
signed min_offset;
|
||||
};
|
||||
|
||||
asm stack_frame* getStackFrame()
|
||||
{
|
||||
mr r3,sp
|
||||
blr
|
||||
}
|
||||
|
||||
static unsigned long long hits = 1, misses = 1;
|
||||
static double hit_ratio = 1.0;
|
||||
|
||||
static const CACHE_BITS = 12;
|
||||
static const CACHE_SIZE = (1 << CACHE_BITS); // 4096 elements should be enough.
|
||||
static const CACHE_SHIFT = (32 - CACHE_BITS); // only consider upper CACHE_BITS of the hashed value.
|
||||
static const CACHE_MASK = (CACHE_SIZE - 1); // only consider lower CACHE_BITS of the hashed value.
|
||||
|
||||
static struct cache_entry {
|
||||
void* savedLR;
|
||||
signed minOffset;
|
||||
const char* functionName;
|
||||
} offset_cache[CACHE_SIZE];
|
||||
|
||||
/**
|
||||
* This routine clears the newly reserved stack space in the caller's frame.
|
||||
* This is done so that the stack won't contain any garbage pointers which
|
||||
* can cause undue retention of garbage.
|
||||
*/
|
||||
pascal void __PROFILE_ENTRY(char* functionName)
|
||||
{
|
||||
stack_frame* myLinkage = getStackFrame()->next;
|
||||
stack_frame* callersLinkage = myLinkage->next;
|
||||
|
||||
signed minOffset = 0;
|
||||
|
||||
// see if we've scanned this routine before, by consulting a direct-mapped cache.
|
||||
// we're just hashing the caller's address, using the Knuth's venerable multiplicative
|
||||
// hash function.
|
||||
void* savedLR = myLinkage->savedLR;
|
||||
unsigned h = ((reinterpret_cast<unsigned>(savedLR) >> 2) * GOLDEN_RATIO) >> CACHE_SHIFT;
|
||||
// unsigned h = ((reinterpret_cast<unsigned>(savedLR) >> 2) * GOLDEN_RATIO) & CACHE_MASK;
|
||||
cache_entry& entry = offset_cache[h];
|
||||
|
||||
if (entry.savedLR == savedLR) {
|
||||
minOffset = entry.minOffset;
|
||||
// ++hits;
|
||||
} else {
|
||||
// scan the caller's prologue, looking for stw instructions. stores to negative
|
||||
// offsets off of sp will tell us where the beginning of the unitialized
|
||||
// frame begins. stmw instructions are also considered.
|
||||
// start scanning at the first instruction before the call.
|
||||
unsigned* pc = -2 + reinterpret_cast<unsigned*>(savedLR);
|
||||
while (*pc != MFLR_R0) {
|
||||
store* instruction = reinterpret_cast<store*>(pc--);
|
||||
unsigned opcode = instruction->opcode;
|
||||
if ((opcode == STW || opcode == STMW) && instruction->destination == R1) {
|
||||
signed offset = instruction->offset;
|
||||
if (offset < minOffset)
|
||||
minOffset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
// cache the minimum offset value, to avoid rescanning the instructions on
|
||||
// subsequent invocations.
|
||||
entry.savedLR = savedLR;
|
||||
entry.minOffset = minOffset;
|
||||
entry.functionName = functionName;
|
||||
// ++misses;
|
||||
}
|
||||
// hit_ratio = (double)hits / (double)misses;
|
||||
|
||||
// clear the space between the linkage area the caller has reserved
|
||||
// for us, and the caller's saved non-volatile registers.
|
||||
signed* ptr = reinterpret_cast<signed*>(myLinkage + 1);
|
||||
signed* end = reinterpret_cast<signed*>(minOffset + reinterpret_cast<char*>(callersLinkage));
|
||||
while (ptr < end) *ptr++ = 0;
|
||||
}
|
||||
|
||||
pascal void __PROFILE_EXIT()
|
||||
{
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#include <profiler.h>
|
||||
#include <Events.h>
|
||||
#include "ProfilerUtils.h"
|
||||
|
||||
//---------------------------------------------
|
||||
|
||||
static Boolean sProfileInProgress = false;
|
||||
void ProfileStart()
|
||||
{
|
||||
if (! sProfileInProgress)
|
||||
{
|
||||
sProfileInProgress = true;
|
||||
if (ProfilerInit(collectDetailed, microsecondsTimeBase, 5000, 500))
|
||||
return;
|
||||
ProfilerSetStatus(true);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void ProfileStop()
|
||||
{
|
||||
if (sProfileInProgress)
|
||||
{
|
||||
ProfilerDump("\pMozilla Profile");
|
||||
ProfilerTerm();
|
||||
sProfileInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void ProfileSuspend()
|
||||
{
|
||||
if (sProfileInProgress)
|
||||
ProfilerSetStatus(false);
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
void ProfileResume()
|
||||
{
|
||||
if (sProfileInProgress)
|
||||
ProfilerSetStatus(true);
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
Boolean ProfileInProgress()
|
||||
{
|
||||
return sProfileInProgress;
|
||||
}
|
||||
|
||||
#endif //DEBUG
|
|
@ -1,62 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Mozilla browser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications, Inc. Portions created by Netscape are
|
||||
* Copyright (C) 1999, Mozilla. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Patrick Beard <beard@netscape.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
NSStartup.c
|
||||
*/
|
||||
|
||||
#include <CodeFragments.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gc_fragments.h"
|
||||
|
||||
extern char __code_start__[]; /* (defined by linker) */
|
||||
extern char __code_end__[]; /* (defined by linker) */
|
||||
extern char __data_start__[]; /* (defined by linker) */
|
||||
extern char __data_end__[]; /* (defined by linker) */
|
||||
|
||||
/* standard __initialize/__terminate routines. */
|
||||
extern pascal OSErr __initialize(const CFragInitBlock* initBlock);
|
||||
extern pascal void __terminate(void);
|
||||
|
||||
pascal OSErr __NSInitialize(const CFragInitBlock* initBlock);
|
||||
pascal void __NSTerminate(void);
|
||||
|
||||
pascal OSErr __NSInitialize(const CFragInitBlock* initBlock)
|
||||
{
|
||||
// let the GC know about this library.
|
||||
GC_register_fragment(__data_start__, __data_end__ + sizeof(char*),
|
||||
__code_start__, __code_end__,
|
||||
initBlock->fragLocator.u.onDisk.fileSpec);
|
||||
|
||||
return __initialize(initBlock);
|
||||
}
|
||||
|
||||
pascal void __NSTerminate()
|
||||
{
|
||||
__terminate();
|
||||
|
||||
// remove this library's global roots.
|
||||
GC_unregister_fragment(__data_start__, __data_end__ + sizeof(char*),
|
||||
__code_start__, __code_end__);
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,43 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "IDE_Options.h"
|
||||
|
||||
/* Common defines for NSStartup */
|
||||
|
||||
/* Turn this on to use the GC based leak detector. */
|
||||
/* #define GC_LEAK_DETECTOR 1 */
|
|
@ -1,101 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Conrad Carlen <ccarlen@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsComponentResContext.h"
|
||||
#include <Resources.h>
|
||||
|
||||
short nsComponentResourceContext::sCompResRefNum = kResFileNotOpened;
|
||||
|
||||
pascal OSErr __NSInitialize(const CFragInitBlock *theInitBlock);
|
||||
pascal OSErr __NSInitializeWithResources(const CFragInitBlock *theInitBlock);
|
||||
|
||||
pascal void __NSTerminate(void);
|
||||
pascal void __NSTerminateWithResources(void);
|
||||
|
||||
//****************************************************************************************
|
||||
// Fragment Init and Termination
|
||||
//****************************************************************************************
|
||||
|
||||
pascal OSErr __NSInitializeWithResources(const CFragInitBlock *theInitBlock)
|
||||
{
|
||||
OSErr err = __NSInitialize(theInitBlock);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
short saveResFile = ::CurResFile();
|
||||
|
||||
short refNum = ::FSpOpenResFile(theInitBlock->fragLocator.u.onDisk.fileSpec, fsRdPerm);
|
||||
nsComponentResourceContext::sCompResRefNum = refNum;
|
||||
|
||||
::UseResFile(saveResFile);
|
||||
|
||||
return ::ResError();
|
||||
}
|
||||
|
||||
pascal void __NSTerminateWithResources(void)
|
||||
{
|
||||
if (nsComponentResourceContext::sCompResRefNum != kResFileNotOpened)
|
||||
::CloseResFile(nsComponentResourceContext::sCompResRefNum);
|
||||
__NSTerminate();
|
||||
}
|
||||
|
||||
//****************************************************************************************
|
||||
// nsComponentResourceContext
|
||||
//****************************************************************************************
|
||||
|
||||
nsComponentResourceContext::nsComponentResourceContext() :
|
||||
mSavedResRefNum(kResFileNotOpened)
|
||||
{
|
||||
}
|
||||
|
||||
nsComponentResourceContext::~nsComponentResourceContext()
|
||||
{
|
||||
if (mSavedResRefNum != kResFileNotOpened)
|
||||
::UseResFile(mSavedResRefNum);
|
||||
}
|
||||
|
||||
Boolean nsComponentResourceContext::BecomeCurrent()
|
||||
{
|
||||
if (sCompResRefNum == kResFileNotOpened)
|
||||
return false;
|
||||
|
||||
mSavedResRefNum = ::CurResFile();
|
||||
::UseResFile(sCompResRefNum);
|
||||
return ::ResError() == noErr;
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Conrad Carlen <ccarlen@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsComponentResContext_h__
|
||||
#define nsComponentResContext_h__
|
||||
|
||||
#include <CodeFragments.h>
|
||||
|
||||
/*
|
||||
* Allows use of resources from the component's resource fork.
|
||||
*
|
||||
* Specify __NSInitializeWithResources and __NSTerminateWithResources
|
||||
* as the entry points of the component and then code within that
|
||||
* component can use this class.
|
||||
*
|
||||
*/
|
||||
|
||||
class nsComponentResourceContext
|
||||
{
|
||||
friend pascal OSErr __NSInitializeWithResources(const CFragInitBlock *theInitBlock);
|
||||
friend pascal void __NSTerminateWithResources(void);
|
||||
|
||||
public:
|
||||
nsComponentResourceContext();
|
||||
~nsComponentResourceContext();
|
||||
|
||||
Boolean BecomeCurrent(); // TRUE if success
|
||||
|
||||
private:
|
||||
static short sCompResRefNum;
|
||||
short mSavedResRefNum;
|
||||
};
|
||||
|
||||
#endif // nsComponentResources_h__
|
|
@ -1,23 +0,0 @@
|
|||
InstLogTraceEventWithDataStructure
|
||||
InstCreateMagnitudeClass
|
||||
InstLogTraceEvent
|
||||
InstCreateSplitHistogramClass
|
||||
InstUpdateGrowth
|
||||
InstCreateDataDescriptor
|
||||
InstDisposeDataDescriptors
|
||||
InstUpdateMagnitudeAbsolute
|
||||
InstLogTraceEventWithData
|
||||
InstCreateTallyClass
|
||||
InstUpdateTally
|
||||
InstDisposeDataDescriptor
|
||||
InstUpdateHistogram
|
||||
InstCreateDataDescriptors
|
||||
InstCreateHistogramClass
|
||||
InstDisposeClass
|
||||
InstCreatePathClass
|
||||
InstDisableClass
|
||||
InstCreateEventTag
|
||||
InstEnableClass
|
||||
InstUpdateMagnitudeDelta
|
||||
InstCreateGrowthClass
|
||||
InstCreateTraceClass
|
|
@ -1,7 +0,0 @@
|
|||
InstallConsole
|
||||
RemoveConsole
|
||||
WriteCharsToConsole
|
||||
ReadCharsFromConsole
|
||||
SIOUXHandleOneEvent
|
||||
SIOUXIsAppWindow
|
||||
SIOUXSettings
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,672 +0,0 @@
|
|||
get__11EnvironmentFPCc # Environment::get(const char*)
|
||||
__dt__11EnvironmentFv # Environment::~Environment()
|
||||
__ct__11EnvironmentFv # Environment::Environment()
|
||||
|
||||
#FSRefParentAndFilename_fopen
|
||||
#FSRef_fopen
|
||||
FSp_fopen
|
||||
__MacOSErrNo
|
||||
__aborting
|
||||
__acoshl
|
||||
__acosl
|
||||
__asinhl
|
||||
__asinl
|
||||
__assertion_failed
|
||||
__atan2l
|
||||
__atanhl
|
||||
__atanl
|
||||
__ceill
|
||||
__copysignl
|
||||
__coshl
|
||||
__cosl
|
||||
__ct__Q23std10_MSLstringFRCQ23std59basic_string<c,Q23std14char_traits<c>,Q23std12allocator<c>>
|
||||
__ct__Q23std4_BCDFr
|
||||
__ct__Q23std7__nInitFv
|
||||
__ct__Q23std7__wInitFv
|
||||
__ct__Q33std8ios_base4InitFv
|
||||
__ctype_map
|
||||
__double_epsilon
|
||||
__double_huge
|
||||
__double_max
|
||||
__double_min
|
||||
__dt__Q23std12strstreambufFv
|
||||
__dt__Q23std7__nInitFv
|
||||
__dt__Q23std7__wInitFv
|
||||
__dt__Q23std8ios_baseFv
|
||||
__erfcl
|
||||
__erfl
|
||||
__exp2l
|
||||
__expl
|
||||
__expm1l
|
||||
__extended_epsilon
|
||||
__extended_huge
|
||||
__extended_max
|
||||
__extended_min
|
||||
__fabsl
|
||||
__fdiml
|
||||
__files
|
||||
__float_huge
|
||||
__float_nan
|
||||
__floorl
|
||||
__fmaxl
|
||||
__fminl
|
||||
__fmodl
|
||||
__fread
|
||||
__frexpl
|
||||
__fwrite
|
||||
__gammal
|
||||
__get_char
|
||||
__get_file_modes
|
||||
__getcreator
|
||||
__gettype
|
||||
__handle_open
|
||||
__hypotl
|
||||
__ldexpl
|
||||
__lgammal
|
||||
__log10l
|
||||
__log1pl
|
||||
__log2l
|
||||
__logbl
|
||||
__logl
|
||||
__lower_map
|
||||
__modfl
|
||||
#__msl_get_system_encoding
|
||||
#__msl_path2fsr
|
||||
#__msl_path2splitfsr
|
||||
#__msl_system_has_new_file_apis
|
||||
#__msl_text2unicode
|
||||
#__msl_unicode2text
|
||||
__nearbyintl
|
||||
__nextafterl
|
||||
__path2fss
|
||||
__powl
|
||||
__put_char
|
||||
__remainderl
|
||||
__remquol
|
||||
__rintl
|
||||
__roundl
|
||||
__sinhl
|
||||
__sinl
|
||||
__sqrtl
|
||||
__system7present
|
||||
__tanhl
|
||||
__tanl
|
||||
__temp_file_mode
|
||||
__truncl
|
||||
__upper_map
|
||||
__vt__Q23std12strstreambuf
|
||||
__vt__Q23std8ios_base
|
||||
__wctype_map
|
||||
__wlower_map
|
||||
__wupper_map
|
||||
_fcreator
|
||||
_filelength
|
||||
_fseek
|
||||
_ftell
|
||||
_ftype
|
||||
_gcvt
|
||||
_heapmin
|
||||
_itoa
|
||||
_itow
|
||||
_strcasecmp
|
||||
_strcmpi
|
||||
_strdate
|
||||
_strdup
|
||||
_stricmp
|
||||
_strlwr
|
||||
_strncasecmp
|
||||
_strncmpi
|
||||
_strnicmp
|
||||
_strnset
|
||||
_strrev
|
||||
_strset
|
||||
_strspnp
|
||||
_strupr
|
||||
_ultoa
|
||||
_wcsdup
|
||||
_wcsicmp
|
||||
_wcslwr
|
||||
_wcsnicmp
|
||||
_wcsnset
|
||||
_wcsrev
|
||||
_wcsset
|
||||
_wcsspnp
|
||||
_wcsupr
|
||||
_wstrrev
|
||||
_wtoi
|
||||
abort
|
||||
abs
|
||||
access
|
||||
acosf
|
||||
acoshf
|
||||
allocated__Q23std12strstreambuf
|
||||
asctime
|
||||
asinf
|
||||
asinhf
|
||||
atan2f
|
||||
atanf
|
||||
atanhf
|
||||
atexit
|
||||
atof
|
||||
atoi
|
||||
atol
|
||||
bsearch
|
||||
btowc
|
||||
ceilf
|
||||
cerr__3std
|
||||
chdir
|
||||
chmod
|
||||
cin__3std
|
||||
clearerr
|
||||
clock
|
||||
clog__3std
|
||||
close
|
||||
copy_ios_base__Q23std8ios_baseFRCQ23std8ios_base
|
||||
copysignf
|
||||
cosf
|
||||
coshf
|
||||
cout__3std
|
||||
creat
|
||||
ctime
|
||||
cuserid
|
||||
difftime
|
||||
div
|
||||
erfcf
|
||||
erff
|
||||
errno
|
||||
exec
|
||||
exit
|
||||
exp2f
|
||||
expf
|
||||
expm1f
|
||||
fabsf
|
||||
fclose
|
||||
fcntl
|
||||
fdimf
|
||||
fdopen
|
||||
feof
|
||||
ferror
|
||||
fflush
|
||||
fgetc
|
||||
fgetpos
|
||||
fgets
|
||||
fgetwc
|
||||
fgetws
|
||||
filelength
|
||||
fileno
|
||||
floorf
|
||||
fmaxf
|
||||
fminf
|
||||
fmodf
|
||||
fopen
|
||||
fprintf
|
||||
fputc
|
||||
fputs
|
||||
fputwc
|
||||
fputws
|
||||
fread
|
||||
freeze__Q23std12strstreambufFb
|
||||
freopen
|
||||
frexpf
|
||||
frozen__Q23std12strstreambuf
|
||||
fscanf
|
||||
fseek
|
||||
fsetpos
|
||||
fstat
|
||||
ftell
|
||||
fwide
|
||||
fwprintf
|
||||
fwrite
|
||||
fwscanf
|
||||
gammaf
|
||||
gcvt
|
||||
getc
|
||||
getchar
|
||||
getcwd
|
||||
getenv
|
||||
getlogin
|
||||
gets
|
||||
getwc
|
||||
getwchar
|
||||
gmtime
|
||||
heapmin
|
||||
hypotf
|
||||
imbue__Q23std8ios_baseFRCQ23std6locale
|
||||
index___Q23std8ios_base
|
||||
init__Q23std12strstreambufFPclPc
|
||||
init__Q23std8ios_baseFPv
|
||||
isatty
|
||||
iswctype
|
||||
itoa
|
||||
itow
|
||||
iword__Q23std8ios_baseFi
|
||||
labs
|
||||
ldexpf
|
||||
ldiv
|
||||
lgammaf
|
||||
llabs
|
||||
lldiv
|
||||
llrint
|
||||
llrintf
|
||||
llrintl
|
||||
llround
|
||||
llroundf
|
||||
llroundl
|
||||
localeconv
|
||||
localtime
|
||||
log10f
|
||||
log1pf
|
||||
log2f
|
||||
logbf
|
||||
logf
|
||||
lrint
|
||||
lrintf
|
||||
lrintl
|
||||
lround
|
||||
lroundf
|
||||
lroundl
|
||||
lseek
|
||||
mblen
|
||||
mbrlen
|
||||
mbrtowc
|
||||
mbsrtowcs
|
||||
mbstowcs
|
||||
mbtowc
|
||||
memchr
|
||||
memcmp
|
||||
memcpy
|
||||
memmove
|
||||
memset
|
||||
mkdir
|
||||
mktime
|
||||
must_round__Q23std4_BCDCFUl
|
||||
nearbyintf
|
||||
nextafter
|
||||
ninit_cnt_s__Q23std7__nInit
|
||||
open
|
||||
overflow__Q23std12strstreambufFi
|
||||
pbackfail__Q23std12strstreambufFi
|
||||
perror
|
||||
powf
|
||||
printf
|
||||
putc
|
||||
putchar
|
||||
puts
|
||||
putwc
|
||||
putwchar
|
||||
pword__Q23std8ios_baseFi
|
||||
qsort
|
||||
raise
|
||||
rand
|
||||
read
|
||||
register_callback__Q23std8ios_baseFPFQ33std8ios_base5eventRQ23std8ios_basei_vi
|
||||
remainderf
|
||||
remove
|
||||
remquof
|
||||
rename
|
||||
rewind
|
||||
rintf
|
||||
rmdir
|
||||
roundf
|
||||
scalbln
|
||||
scalblnf
|
||||
scalblnl
|
||||
scalbn
|
||||
scalbnf
|
||||
scalbnl
|
||||
scanf
|
||||
seekoff__Q23std12strstreambufFlQ33std8ios_base7seekdirQ33std8ios_base8openmode
|
||||
seekpos__Q23std12strstreambufFQ23std7fpos<i>Q33std8ios_base8openmode
|
||||
setbuf
|
||||
setbuf__Q23std12strstreambufFPcl
|
||||
setlocale
|
||||
setvbuf
|
||||
signal
|
||||
sinf
|
||||
sinhf
|
||||
sleep
|
||||
snprintf
|
||||
sprintf
|
||||
sqrtf
|
||||
srand
|
||||
sscanf
|
||||
stat
|
||||
strcasecmp
|
||||
strcat
|
||||
strchr
|
||||
strcmp
|
||||
strcmpi
|
||||
strcoll
|
||||
strcpy
|
||||
strcspn
|
||||
strdate
|
||||
strdup
|
||||
strerror
|
||||
strftime
|
||||
stricmp
|
||||
strlen
|
||||
strlwr
|
||||
strncasecmp
|
||||
strncat
|
||||
strncmp
|
||||
strncmpi
|
||||
strncpy
|
||||
strnicmp
|
||||
strnset
|
||||
strpbrk
|
||||
strrchr
|
||||
strrev
|
||||
strset
|
||||
strspn
|
||||
strspnp
|
||||
strstr
|
||||
strtod
|
||||
strtok
|
||||
strtol
|
||||
strtold
|
||||
strtoll
|
||||
strtoul
|
||||
strtoull
|
||||
strupr
|
||||
strxfrm
|
||||
swprintf
|
||||
swscanf
|
||||
sync_with_stdio__Q23std8ios_baseFb
|
||||
tanf
|
||||
tanhf
|
||||
time
|
||||
tmpfile
|
||||
tmpnam
|
||||
to_long_double__Q23std4_BCDCFv
|
||||
to_string__Q23std4_BCDCFiRi
|
||||
towctrans
|
||||
truncf
|
||||
ttyname
|
||||
ultoa
|
||||
umask
|
||||
uname
|
||||
underflow__Q23std12strstreambufFv
|
||||
ungetc
|
||||
ungetwc
|
||||
unlink
|
||||
utime
|
||||
utimes
|
||||
vfprintf
|
||||
vfscanf
|
||||
vfwprintf
|
||||
vfwscanf
|
||||
vprintf
|
||||
vscanf
|
||||
vsnprintf
|
||||
vsprintf
|
||||
vsscanf
|
||||
vswprintf
|
||||
vswscanf
|
||||
vwprintf
|
||||
vwscanf
|
||||
watof
|
||||
watoi
|
||||
watol
|
||||
wcerr__3std
|
||||
wcin__3std
|
||||
wclog__3std
|
||||
wcout__3std
|
||||
wcrtomb
|
||||
wcscat
|
||||
wcschr
|
||||
wcscmp
|
||||
wcscoll
|
||||
wcscpy
|
||||
wcscspn
|
||||
wcsdup
|
||||
wcsftime
|
||||
wcsicmp
|
||||
wcslen
|
||||
wcslwr
|
||||
wcsncat
|
||||
wcsncmp
|
||||
wcsncpy
|
||||
wcsnicmp
|
||||
wcsnset
|
||||
wcspbrk
|
||||
wcsrchr
|
||||
wcsrev
|
||||
wcsrtombs
|
||||
wcsset
|
||||
wcsspn
|
||||
wcsspnp
|
||||
wcsstr
|
||||
wcstod
|
||||
wcstok
|
||||
wcstol
|
||||
wcstoll
|
||||
wcstombs
|
||||
wcstoul
|
||||
wcstoull
|
||||
wcsupr
|
||||
wcsxfrm
|
||||
wctob
|
||||
wctomb
|
||||
wctrans
|
||||
wctype
|
||||
winit_cnt_s__Q23std7__wInit
|
||||
wmemchr
|
||||
wmemcmp
|
||||
wmemcpy
|
||||
wmemmove
|
||||
wmemset
|
||||
wprintf
|
||||
write
|
||||
wscanf
|
||||
wstrrev
|
||||
wtoi
|
||||
|
||||
InitializeMacToolbox
|
||||
|
||||
#__ptmf_null
|
||||
#__vec_longjmp
|
||||
#longjmp
|
||||
#__terminate
|
||||
#__initialize
|
||||
#__destroy_new_array3
|
||||
#__destroy_new_array2
|
||||
#__destroy_new_array
|
||||
#__NSTerminate
|
||||
#__NSInitialize
|
||||
#vec_free
|
||||
#vec_realloc
|
||||
#vec_calloc
|
||||
#vec_malloc
|
||||
#__malloc_free_all
|
||||
#__pool_free_all
|
||||
calloc
|
||||
realloc
|
||||
free
|
||||
malloc
|
||||
#__pool_alloc_clear
|
||||
#__pool_realloc
|
||||
#__pool_free
|
||||
#__pool_alloc
|
||||
#__msize
|
||||
#__report_on_heap
|
||||
#__report_on_pool_heap
|
||||
#deallocate_from_fixed_pools
|
||||
#allocate_from_fixed_pools
|
||||
#__init_pool_obj
|
||||
nothrow
|
||||
__dla__FPv # operator delete[](void*)
|
||||
__nwa__FUlRCQ23std9nothrow_t # operator new[](unsigned long,const std::nothrow_t&)
|
||||
__nwa__FUl # operator new[](unsigned long)
|
||||
__dl__FPv # operator delete(void*)
|
||||
__nw__FUl # operator new(unsigned long)
|
||||
__nw__FUlRCQ23std9nothrow_t # operator new(unsigned long,const std::nothrow_t&)
|
||||
GC_stderr
|
||||
GC_stdout
|
||||
GC_trace_object
|
||||
GC_mark_object
|
||||
MWUnmangle
|
||||
GC_malloc_atomic
|
||||
GC_address_to_source
|
||||
GC_gcollect
|
||||
GC_generic_init_threads
|
||||
GC_clear_roots
|
||||
GC_unregister_fragment
|
||||
GC_register_fragment
|
||||
#__sys_pointer_size
|
||||
#__sys_free
|
||||
#__sys_alloc
|
||||
|
||||
FSpDirectoryCopy
|
||||
FSpFilteredDirectoryCopy
|
||||
DirectoryCopy
|
||||
FilteredDirectoryCopy
|
||||
FSpFileCopy
|
||||
FileCopy
|
||||
FSpCreateResFileCompat
|
||||
FSpOpenResFileCompat
|
||||
FSpExchangeFilesCompat
|
||||
FSpCatMoveCompat
|
||||
FSpRenameCompat
|
||||
FSpRstFLockCompat
|
||||
FSpSetFLockCompat
|
||||
FSpSetFInfoCompat
|
||||
FSpGetFInfoCompat
|
||||
FSpDeleteCompat
|
||||
FSpDirCreateCompat
|
||||
FSpCreateCompat
|
||||
FSpOpenRFCompat
|
||||
FSpOpenDFCompat
|
||||
FSMakeFSSpecCompat
|
||||
LocationFromFullPath
|
||||
FSpLocationFromFullPath
|
||||
FSpGetFullPath
|
||||
GetFullPath
|
||||
FSpIterateDirectory
|
||||
IterateDirectory
|
||||
FSpDTCopyComment
|
||||
DTCopyComment
|
||||
FSpDTGetComment
|
||||
DTGetComment
|
||||
FSpDTSetComment
|
||||
DTSetComment
|
||||
DTGetIcon
|
||||
FSpDTGetAPPL
|
||||
DTGetAPPL
|
||||
FSpDTXGetAPPL
|
||||
DTXGetAPPL
|
||||
DTOpen
|
||||
GetUGEntry
|
||||
FSpUnshare
|
||||
Unshare
|
||||
FSpShare
|
||||
Share
|
||||
VolumeMount
|
||||
GetVolMountInfo
|
||||
GetVolMountInfoSize
|
||||
FSpMoveRename
|
||||
HMoveRename
|
||||
FSpCopyFile
|
||||
HCopyFile
|
||||
HMapName
|
||||
HMapID
|
||||
FSpSetDirAccess
|
||||
HSetDirAccess
|
||||
FSpGetDirAccess
|
||||
HGetDirAccess
|
||||
HGetLogInInfo
|
||||
FSpSetForeignPrivs
|
||||
SetForeignPrivs
|
||||
FSpGetForeignPrivs
|
||||
GetForeignPrivs
|
||||
UnlockRange
|
||||
LockRange
|
||||
FlushFile
|
||||
DeleteFileIDRef
|
||||
FSpCreateFileIDRef
|
||||
CreateFileIDRef
|
||||
FSpResolveFileIDRef
|
||||
ResolveFileIDRef
|
||||
ExchangeFiles
|
||||
FSpCreateMinimum
|
||||
HCreateMinimum
|
||||
HGetVolParms
|
||||
GetUGEntries
|
||||
RetrieveAFPXVolMountInfo
|
||||
BuildAFPXVolMountInfo
|
||||
RetrieveAFPVolMountInfo
|
||||
BuildAFPVolMountInfo
|
||||
FSpMoveRenameCompat
|
||||
HMoveRenameCompat
|
||||
FSpCopyDirectoryAccess
|
||||
CopyDirectoryAccess
|
||||
FSpGetFileLocation
|
||||
GetFileLocation
|
||||
CopyFork
|
||||
FSWriteVerify
|
||||
FSWriteNoCache
|
||||
FSReadNoCache
|
||||
FSpOpenRFAware
|
||||
HOpenRFAware
|
||||
FSpOpenAware
|
||||
HOpenAware
|
||||
FSpCopyFileMgrAttributes
|
||||
CopyFileMgrAttributes
|
||||
FSpClearHasBeenInited
|
||||
ClearHasBeenInited
|
||||
FSpClearHasCustomIcon
|
||||
ClearHasCustomIcon
|
||||
FSpSetHasCustomIcon
|
||||
SetHasCustomIcon
|
||||
FSpClearIsStationery
|
||||
ClearIsStationery
|
||||
FSpSetIsStationery
|
||||
SetIsStationery
|
||||
FSpClearNameLocked
|
||||
ClearNameLocked
|
||||
FSpSetNameLocked
|
||||
SetNameLocked
|
||||
FSpClearIsInvisible
|
||||
ClearIsInvisible
|
||||
FSpSetIsInvisible
|
||||
SetIsInvisible
|
||||
FSpChangeFDFlags
|
||||
ChangeFDFlags
|
||||
FSpChangeCreatorType
|
||||
ChangeCreatorType
|
||||
FSpBumpDate
|
||||
BumpDate
|
||||
FSpGetFileSize
|
||||
GetFileSize
|
||||
FSpCheckObjectLock
|
||||
CheckObjectLock
|
||||
DeleteDirectory
|
||||
DeleteDirectoryContents
|
||||
GetDirItems
|
||||
GetObjectLocation
|
||||
GetFilenameFromPathname
|
||||
GetParentID
|
||||
FSpGetIOACUser
|
||||
GetIOACUser
|
||||
GetDirName
|
||||
FSpGetDirectoryID
|
||||
GetDirectoryID
|
||||
FSpSetDInfo
|
||||
SetDInfo
|
||||
FSpGetDInfo
|
||||
GetDInfo
|
||||
SetDefault
|
||||
OnLine
|
||||
GetVolFileSystemID
|
||||
CheckVolLock
|
||||
XGetVInfo
|
||||
HGetVInfo
|
||||
DetermineVRefNum
|
||||
GetCatInfoNoName
|
||||
XGetVolumeInfoNoName
|
||||
GetVolumeInfoNoName
|
||||
GetTempBuffer
|
||||
TruncPString
|
||||
CreatorTypeFileSearch
|
||||
NameFileSearch
|
||||
PBCatSearchSyncCompat
|
||||
IndexedSearch
|
|
@ -1,26 +0,0 @@
|
|||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
# Build NSStdLibStubs
|
||||
|
||||
Evaluate % = ("{{SourceFile}}" =~ /(Å:)¨0Å/)
|
||||
|
||||
MakeStub "{{SourceFile}}" -o "{{¨0}}:::dist:client_stubs:NSStdLibStubs" ¶
|
||||
-fragname NSStdLib ¶
|
||||
-vercur 400 -verdef 400 -verimp 400
|
|
@ -1,41 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* Non debug specific defines for NSStdLib */
|
||||
|
||||
#include "MacPrefix.h"
|
||||
#include "NSStdLibConfig.h"
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,26 +0,0 @@
|
|||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
# Build NSStdLibStubs
|
||||
|
||||
Evaluate % = ("{{SourceFile}}" =~ /(Å:)¨0Å/)
|
||||
|
||||
MakeStub "{{SourceFile}}" -o "{{¨0}}:::dist:client_stubs:NSStdLibStubs" ¶
|
||||
-fragname NSStdLib ¶
|
||||
-vercur 400 -verdef 400 -verimp 400
|
|
@ -1,44 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* Common defines for both debug & non-debug versions NSStdLib */
|
||||
|
||||
#define _MSL_IMP_EXP __declspec(export)
|
||||
|
||||
// So we can continue to run on 8.6
|
||||
#define _MSL_USE_NEW_FILE_APIS 0
|
||||
#define _MSL_USE_OLD_FILE_APIS 1
|
|
@ -1,43 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* Debug specific defines for the NSStdLib */
|
||||
|
||||
#include "MacPrefix_debug.h"
|
||||
#include "NSStdLibConfig.h"
|
||||
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
# GC exports.
|
||||
GC_add_roots
|
||||
GC_remove_roots
|
||||
GC_clear_roots
|
||||
GC_generic_init_threads
|
||||
GC_gcollect
|
||||
GC_stdout
|
||||
GC_stderr
|
|
@ -1,10 +0,0 @@
|
|||
#library
|
||||
__PROFILE_EXIT
|
||||
__PROFILE_ENTRY
|
||||
|
||||
#utils
|
||||
ProfileStart
|
||||
ProfileStop
|
||||
ProfileSuspend
|
||||
ProfileResume
|
||||
ProfileInProgress
|
|
@ -1,4 +0,0 @@
|
|||
InitializeSIOUX
|
||||
IsSIOUXWindow
|
||||
SIOUXHandleOneEvent
|
||||
SIOUXSettings
|
|
@ -1,70 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
Definitions for all routines normally found in string.h, but not there in the Metrowerks
|
||||
ANSII headers.
|
||||
*/
|
||||
|
||||
#ifndef __MACTYPES__
|
||||
#include <MacTypes.h>
|
||||
#endif
|
||||
|
||||
#ifndef __QUICKDRAW__
|
||||
#include <Quickdraw.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern char *strdup(const char *source);
|
||||
|
||||
extern int strcasecmp(const char*, const char*);
|
||||
|
||||
extern int strncasecmp(const char*, const char*, int length);
|
||||
|
||||
extern void InitializeMacToolbox(void); // also calls InitializeSIOUX(false) if DEBUG.
|
||||
|
||||
#if DEBUG
|
||||
extern void InitializeSIOUX(unsigned char isStandAlone);
|
||||
extern Boolean IsSIOUXWindow(WindowPtr inWindow);
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,332 +0,0 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Patrick C. Beard <beard@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Console stubs that send all console output to the Mac OS X Console.app, or
|
||||
// to the terminal, if Mozilla is launched from the command line.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <console.h>
|
||||
#include <size_t.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <CFURL.h>
|
||||
#include <CFBundle.h>
|
||||
#include <CFString.h>
|
||||
#include <MacErrors.h>
|
||||
#include <Gestalt.h>
|
||||
#include <CodeFragments.h>
|
||||
#include <Fonts.h>
|
||||
#include <TextEdit.h>
|
||||
#include <Controls.h>
|
||||
|
||||
#include <SIOUX.h>
|
||||
#include <SIOUXWindows.h>
|
||||
#include <console_io.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static CFBundleRef getBundle(CFStringRef frameworkPath)
|
||||
{
|
||||
CFBundleRef bundle = NULL;
|
||||
|
||||
// Make a CFURLRef from the CFString representation of the bundle's path.
|
||||
// See the Core Foundation URL Services chapter for details.
|
||||
CFURLRef bundleURL = CFURLCreateWithFileSystemPath(NULL, frameworkPath, kCFURLPOSIXPathStyle, true);
|
||||
if (bundleURL != NULL) {
|
||||
bundle = CFBundleCreate(NULL, bundleURL);
|
||||
if (bundle != NULL)
|
||||
CFBundleLoadExecutable(bundle);
|
||||
CFRelease(bundleURL);
|
||||
}
|
||||
|
||||
return bundle;
|
||||
}
|
||||
|
||||
static void* getSystemFunction(CFStringRef functionName)
|
||||
{
|
||||
static CFBundleRef systemBundle = getBundle(CFSTR("/System/Library/Frameworks/System.framework"));
|
||||
if (systemBundle) return CFBundleGetFunctionPointerForName(systemBundle, functionName);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Useful Carbon-CFM debugging tool, printf that goes to the system console.
|
||||
|
||||
typedef int (*io_proc_ptr) (int fd, void* buffer, long count);
|
||||
|
||||
#if TARGET_CARBON
|
||||
static io_proc_ptr system_read = (io_proc_ptr) getSystemFunction(CFSTR("read"));
|
||||
static io_proc_ptr system_write = (io_proc_ptr) getSystemFunction(CFSTR("write"));
|
||||
#else
|
||||
static io_proc_ptr system_read = 0;
|
||||
static io_proc_ptr system_write = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following four functions provide the UI for the console package.
|
||||
* Users wishing to replace SIOUX with their own console package need
|
||||
* only provide the four functions below in a library.
|
||||
*/
|
||||
|
||||
static CFragConnectionID gConsoleLibrary;
|
||||
|
||||
static void* find_symbol(CFragConnectionID connection, StringPtr symName)
|
||||
{
|
||||
Ptr symAddr;
|
||||
if (FindSymbol(gConsoleLibrary, symName, &symAddr, NULL) == noErr)
|
||||
return symAddr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* extern short InstallConsole(short fd);
|
||||
*
|
||||
* Installs the Console package, this function will be called right
|
||||
* before any read or write to one of the standard streams.
|
||||
*
|
||||
* short fd: The stream which we are reading/writing to/from.
|
||||
* returns short: 0 no error occurred, anything else error.
|
||||
*/
|
||||
|
||||
short InstallConsole(short fd)
|
||||
{
|
||||
long version;
|
||||
OSErr err = Gestalt(gestaltSystemVersion, &version);
|
||||
if (err == noErr && version < 0x00001000) {
|
||||
// load the "NSConsole" library.
|
||||
err = GetSharedLibrary("\pNSConsole", kCompiledCFragArch, kReferenceCFrag,
|
||||
&gConsoleLibrary, NULL, NULL);
|
||||
if (err == noErr) {
|
||||
atexit(&RemoveConsole);
|
||||
// transfer the SIOUX settings.
|
||||
tSIOUXSettings *sioux_settings = (tSIOUXSettings*) find_symbol(gConsoleLibrary, "\pSIOUXSettings");
|
||||
if (sioux_settings) {
|
||||
*sioux_settings = SIOUXSettings;
|
||||
short (*install_console) (short) = (short (*) (short)) find_symbol(gConsoleLibrary, "\pInstallConsole");
|
||||
if (install_console)
|
||||
return install_console(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* extern void RemoveConsole(void);
|
||||
*
|
||||
* Removes the console package. It is called after all other streams
|
||||
* are closed and exit functions (installed by either atexit or _atexit)
|
||||
* have been called. Since there is no way to recover from an error,
|
||||
* this function doesn't need to return any.
|
||||
*/
|
||||
|
||||
void RemoveConsole()
|
||||
{
|
||||
if (gConsoleLibrary) {
|
||||
void (*remove_console) (void) = (void (*) (void)) find_symbol(gConsoleLibrary, "\pInstallConsole");
|
||||
if (remove_console)
|
||||
remove_console();
|
||||
CloseConnection(&gConsoleLibrary);
|
||||
gConsoleLibrary = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* extern long WriteCharsToConsole(char *buffer, long n);
|
||||
*
|
||||
* Writes a stream of output to the Console window. This function is
|
||||
* called by write.
|
||||
*
|
||||
* char *buffer: Pointer to the buffer to be written.
|
||||
* long n: The length of the buffer to be written.
|
||||
* returns short: Actual number of characters written to the stream,
|
||||
* -1 if an error occurred.
|
||||
*/
|
||||
|
||||
long WriteCharsToConsole(char *buffer, long n)
|
||||
{
|
||||
if (gConsoleLibrary) {
|
||||
static long (*write_chars) (char*, long) = (long (*) (char*, long)) find_symbol(gConsoleLibrary, "\pWriteCharsToConsole");
|
||||
if (write_chars)
|
||||
return write_chars(buffer, n);
|
||||
} else {
|
||||
for (char* cr = strchr(buffer, '\r'); cr; cr = strchr(cr + 1, '\r'))
|
||||
*cr = '\n';
|
||||
if (system_write) return system_write(1, buffer, n);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* extern long ReadCharsFromConsole(char *buffer, long n);
|
||||
*
|
||||
* Reads from the Console into a buffer. This function is called by
|
||||
* read.
|
||||
*
|
||||
* char *buffer: Pointer to the buffer which will recieve the input.
|
||||
* long n: The maximum amount of characters to be read (size of
|
||||
* buffer).
|
||||
* returns short: Actual number of characters read from the stream,
|
||||
* -1 if an error occurred.
|
||||
*/
|
||||
|
||||
long ReadCharsFromConsole(char *buffer, long n)
|
||||
{
|
||||
if (gConsoleLibrary) {
|
||||
static long (*read_chars) (char*, long) = (long (*) (char*, long)) find_symbol(gConsoleLibrary, "\pReadCharsFromConsole");
|
||||
if (read_chars)
|
||||
return read_chars(buffer, n);
|
||||
} else {
|
||||
if (system_read) return system_read(0, buffer, n);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern char *__ttyname(long fildes)
|
||||
{
|
||||
if (fildes >= 0 && fildes <= 2)
|
||||
return "console";
|
||||
return (0L);
|
||||
}
|
||||
|
||||
int kbhit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getch(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clrscr()
|
||||
{
|
||||
/* Could send the appropriate VT100 sequence here... */
|
||||
}
|
||||
|
||||
tSIOUXSettings SIOUXSettings = {
|
||||
true, true, true, false, true, false, NULL,
|
||||
4, 80, 24, 0, 0, kFontIDMonaco,
|
||||
9, normal, true, true, false
|
||||
};
|
||||
|
||||
short SIOUXHandleOneEvent(EventRecord *userevent)
|
||||
{
|
||||
if (gConsoleLibrary) {
|
||||
static short (*handle_event) (EventRecord*) = (short (*) (EventRecord*)) find_symbol(gConsoleLibrary, "\pSIOUXHandleOneEvent");
|
||||
if (handle_event)
|
||||
return handle_event(userevent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Boolean SIOUXIsAppWindow(WindowPtr window)
|
||||
{
|
||||
if (gConsoleLibrary) {
|
||||
static Boolean (*is_app_window) (WindowPtr) = (Boolean (*) (WindowPtr)) find_symbol(gConsoleLibrary, "\pSIOUXIsAppWindow");
|
||||
if (is_app_window)
|
||||
return is_app_window(window);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower level console implementation. Let's us distinguish stdout from stderr.
|
||||
*/
|
||||
|
||||
static int check_console()
|
||||
{
|
||||
static short status = (InstallConsole(0) == 0);
|
||||
return status;
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
|
||||
int __read_console(__file_handle handle, unsigned char * buffer, size_t * count, __idle_proc idle_proc)
|
||||
{
|
||||
if (!check_console())
|
||||
return(__io_error);
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
long n = *count;
|
||||
if (gConsoleLibrary) {
|
||||
static long (*read_chars) (char*, long) = (long (*) (char*, long)) find_symbol(gConsoleLibrary, "\pReadCharsFromConsole");
|
||||
if (read_chars)
|
||||
n = read_chars((char*)buffer, n);
|
||||
else
|
||||
n = -1;
|
||||
} else {
|
||||
if (system_read)
|
||||
n = system_read(handle, buffer, n);
|
||||
else
|
||||
n = -1;
|
||||
}
|
||||
*count = n;
|
||||
return (n == -1 ? __io_error : __no_io_error);
|
||||
}
|
||||
|
||||
int __write_console(__file_handle handle, unsigned char * buffer, size_t * count, __idle_proc idle_proc)
|
||||
{
|
||||
if (!check_console())
|
||||
return(__io_error);
|
||||
|
||||
long n = *count;
|
||||
if (gConsoleLibrary) {
|
||||
static long (*write_chars) (char*, long) = (long (*) (char*, long)) find_symbol(gConsoleLibrary, "\pWriteCharsToConsole");
|
||||
if (write_chars)
|
||||
n = write_chars((char*)buffer, n);
|
||||
else
|
||||
n = -1;
|
||||
} else {
|
||||
if (system_write) {
|
||||
for (char* cr = strchr((char*)buffer, '\r'); cr; cr = strchr(cr + 1, '\r'))
|
||||
*cr = '\n';
|
||||
n = system_write(handle, buffer, n);
|
||||
} else {
|
||||
n = -1;
|
||||
}
|
||||
}
|
||||
*count = n;
|
||||
return (n == -1 ? __io_error : __no_io_error);
|
||||
}
|
||||
|
||||
int __close_console(__file_handle handle)
|
||||
{
|
||||
return(__no_io_error);
|
||||
}
|
|
@ -1,238 +0,0 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "macstdlibextras.h"
|
||||
|
||||
|
||||
#include <MacTypes.h>
|
||||
#include <Memory.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <Quickdraw.h>
|
||||
#include <TextServices.h>
|
||||
#include <Movies.h>
|
||||
|
||||
#if !defined(__MSL__) || (__MSL__ < 0x7001)
|
||||
|
||||
int strcmpcore(const char*, const char*, int, int);
|
||||
|
||||
|
||||
/*
|
||||
size_t strlen(const char *source)
|
||||
{
|
||||
size_t currentLength = 0;
|
||||
|
||||
if (source == NULL)
|
||||
return currentLength;
|
||||
|
||||
while (*source++ != '\0')
|
||||
currentLength++;
|
||||
|
||||
return currentLength;
|
||||
}
|
||||
*/
|
||||
|
||||
int strcmpcore(const char *str1, const char *str2, int caseSensitive, int length)
|
||||
{
|
||||
char currentChar1, currentChar2;
|
||||
int compareLength = (length >= 0);
|
||||
|
||||
while (1) {
|
||||
|
||||
if (compareLength) {
|
||||
|
||||
if ( length <= 0 )
|
||||
return 0;
|
||||
length--;
|
||||
|
||||
}
|
||||
|
||||
currentChar1 = *str1;
|
||||
currentChar2 = *str2;
|
||||
|
||||
if (!caseSensitive) {
|
||||
|
||||
if ((currentChar1 >= 'a') && (currentChar1 <= 'z'))
|
||||
currentChar1 += ('A' - 'a');
|
||||
|
||||
if ((currentChar2 >= 'a') && (currentChar2 <= 'z'))
|
||||
currentChar2 += ('A' - 'a');
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (currentChar1 == '\0')
|
||||
break;
|
||||
|
||||
if (currentChar1 != currentChar2)
|
||||
return currentChar1 - currentChar2;
|
||||
|
||||
str1++;
|
||||
str2++;
|
||||
|
||||
}
|
||||
|
||||
return currentChar1 - currentChar2;
|
||||
}
|
||||
|
||||
/*
|
||||
int strcmp(const char *str1, const char *str2)
|
||||
{
|
||||
return strcmpcore(str1, str2, true, -1);
|
||||
}
|
||||
*/
|
||||
|
||||
int strcasecmp(const char *str1, const char *str2)
|
||||
{
|
||||
/* This doesnÕt really belong here; but since it uses strcmpcore, weÕll keep it. */
|
||||
return strcmpcore(str1, str2, false, -1);
|
||||
}
|
||||
|
||||
|
||||
int strncasecmp(const char *str1, const char *str2, int length)
|
||||
{
|
||||
/* This doesnÕt really belong here; but since it uses strcmpcore, weÕll keep it. */
|
||||
return strcmpcore(str1, str2, false, length);
|
||||
}
|
||||
|
||||
|
||||
char *strdup(const char *source)
|
||||
{
|
||||
char *newAllocation;
|
||||
size_t stringLength;
|
||||
|
||||
/*
|
||||
#ifdef DEBUG
|
||||
PR_ASSERT(source);
|
||||
#endif
|
||||
*/
|
||||
|
||||
stringLength = strlen(source) + 1;
|
||||
|
||||
/* since this gets freed by an XP_FREE, it must do an XP_ALLOC */
|
||||
/* newAllocation = (char *)XP_ALLOC(stringLength); */
|
||||
newAllocation = (char *)malloc(stringLength);
|
||||
if (newAllocation == NULL)
|
||||
return NULL;
|
||||
BlockMoveData(source, newAllocation, stringLength);
|
||||
return newAllocation;
|
||||
}
|
||||
|
||||
#endif // !defined(__MSL__) || (__MSL__ < 0x7001)
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
void InitializeMacToolbox(void)
|
||||
{
|
||||
// once only, macintosh specific initialization
|
||||
static Boolean alreadyInitialized = false;
|
||||
if (!alreadyInitialized)
|
||||
{
|
||||
long CMMavail = 0;
|
||||
|
||||
alreadyInitialized = true;
|
||||
#if !TARGET_CARBON
|
||||
// pinkerton - don't need to init toolbox under Carbon. They finally do that for us!
|
||||
InitGraf(&qd.thePort);
|
||||
InitFonts();
|
||||
InitWindows();
|
||||
InitMenus();
|
||||
TEInit();
|
||||
InitDialogs(0);
|
||||
InitCursor();
|
||||
Gestalt(gestaltContextualMenuAttr, &CMMavail);
|
||||
if ((CMMavail == gestaltContextualMenuTrapAvailable) &&
|
||||
((long)InitContextualMenus != kUnresolvedCFragSymbolAddress))
|
||||
InitContextualMenus();
|
||||
|
||||
InitTSMAwareApplication();
|
||||
#endif
|
||||
|
||||
// init QuickTime if we have it
|
||||
if ((long)EnterMovies != kUnresolvedCFragSymbolAddress)
|
||||
EnterMovies();
|
||||
|
||||
#if DEBUG
|
||||
InitializeSIOUX(false);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
#if DEBUG
|
||||
|
||||
#include <SIOUX.h>
|
||||
|
||||
void InitializeSIOUX(unsigned char isStandAlone)
|
||||
{
|
||||
|
||||
SIOUXSettings.initializeTB = isStandAlone;
|
||||
SIOUXSettings.standalone = isStandAlone;
|
||||
SIOUXSettings.setupmenus = isStandAlone;
|
||||
SIOUXSettings.autocloseonquit = true;
|
||||
SIOUXSettings.asktosaveonclose = false;
|
||||
SIOUXSettings.showstatusline = false;
|
||||
|
||||
if (isStandAlone)
|
||||
{
|
||||
SIOUXSettings.toppixel = 42;
|
||||
SIOUXSettings.leftpixel = 6;
|
||||
SIOUXSettings.rows = 40;
|
||||
SIOUXSettings.columns = 82;
|
||||
}
|
||||
else
|
||||
{
|
||||
SIOUXSettings.toppixel = 480;
|
||||
SIOUXSettings.leftpixel = 4;
|
||||
SIOUXSettings.rows = 20;
|
||||
SIOUXSettings.columns = 100;
|
||||
}
|
||||
|
||||
//InstallConsole();
|
||||
}
|
||||
|
||||
Boolean IsSIOUXWindow(WindowPtr inWindow)
|
||||
{
|
||||
return SIOUXIsAppWindow(inWindow);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,134 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Mozilla browser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications, Inc. Portions created by Netscape are
|
||||
* Copyright (C) 1999, Mozilla. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Patrick Beard <beard@netscape.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
This file must precede sysenv.c in the link order, so that this implementation of
|
||||
getenv() will override Metrowerks' standard, useless version.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/**
|
||||
* Provide a simple environment variable table, that gets loaded once per run of a program.
|
||||
*/
|
||||
class Environment {
|
||||
public:
|
||||
Environment();
|
||||
~Environment();
|
||||
|
||||
char* get(const char* name);
|
||||
|
||||
private:
|
||||
struct Variable {
|
||||
Variable* mNext;
|
||||
char* mName;
|
||||
char* mValue;
|
||||
|
||||
Variable(const char* name, const char* value)
|
||||
: mNext(NULL), mName(NULL), mValue(NULL)
|
||||
{
|
||||
mName = new char[::strlen(name) + 1];
|
||||
if (mName != NULL)
|
||||
::strcpy(mName, name);
|
||||
if (value != NULL) {
|
||||
mValue = new char[::strlen(value) + 1];
|
||||
if (mValue != NULL)
|
||||
::strcpy(mValue, value);
|
||||
}
|
||||
}
|
||||
|
||||
~Variable() {
|
||||
if (mName) delete[] mName;
|
||||
if (mValue) delete[] mValue;
|
||||
}
|
||||
};
|
||||
Variable* mVariables;
|
||||
};
|
||||
|
||||
Environment::Environment()
|
||||
: mVariables(NULL)
|
||||
{
|
||||
// opens "ENVIRONMENT" file in current application's directory.
|
||||
FILE* f = ::fopen("ENVIRONMENT", "r");
|
||||
if (f != NULL) {
|
||||
char line[1024];
|
||||
while (::fgets(line, sizeof(line), f) != NULL) {
|
||||
// allow comments starting with "#" or "//"
|
||||
if (line[0] == '#' || (line[0] == '/' && line[1] == '/'))
|
||||
continue;
|
||||
|
||||
// trim trailing linefeed.
|
||||
int len = ::strlen(line);
|
||||
if (line[len - 1] == '\n')
|
||||
line[--len] = '\0';
|
||||
|
||||
// ignore leading white space.
|
||||
char* name = line;
|
||||
while (isspace(*name)) ++name;
|
||||
|
||||
// look for value.
|
||||
char* value = "1";
|
||||
char* eq = ::strchr(name, '=');
|
||||
if (eq != NULL) {
|
||||
value = eq + 1;
|
||||
*eq = '\0';
|
||||
}
|
||||
|
||||
Variable* var = new Variable(name, value);
|
||||
var->mNext = mVariables;
|
||||
mVariables = var;
|
||||
}
|
||||
::fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
Environment::~Environment()
|
||||
{
|
||||
Variable* var = mVariables;
|
||||
while (var != NULL) {
|
||||
Variable* next = var->mNext;
|
||||
delete var;
|
||||
var = next;
|
||||
}
|
||||
}
|
||||
|
||||
char* Environment::get(const char* name)
|
||||
{
|
||||
Variable** link = &mVariables;
|
||||
Variable* var = *link;
|
||||
while (var != NULL) {
|
||||
if (::strcmp(var->mName, name) == 0)
|
||||
return var->mValue;
|
||||
link = &var->mNext;
|
||||
var = *link;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* std::getenv(const char * name)
|
||||
{
|
||||
static Environment env;
|
||||
return env.get(name);
|
||||
}
|
Загрузка…
Ссылка в новой задаче