Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 #include "defs.h" 00037 #include "cxx_memory.h" 00038 #include "errors.h" 00039 00040 MEM_POOL* _dummy_new_mempool = (MEM_POOL*) -1; 00041 MEM_POOL* _dummy_delete_mempool = (MEM_POOL*) -1; 00042 size_t _dummy_pad = 0; 00043 00044 int _alloc_callsite_line = 0; 00045 const char *_alloc_callsite_file = NULL; 00046 00047 /* Description of new scheme: 00048 * ========================== 00049 * 00050 * Many C++ implementations don't support calling destructors for 00051 * array objects allocated using placement new (which we need since we 00052 * want to allocate memory from the memory pools rather than malloc). 00053 * In fact, I believe the language is either ambiguous about this, or 00054 * explicitly does not support this. 00055 * 00056 * We need to mangle new/delete to call MEM_POOL_Alloc and MEM_POOL_FREE 00057 * instead of malloc and free. 00058 * 00059 * We used to do this using placement new/delete in which we would pass in 00060 * extra arguments to new/delete (e.g. mempool) and then have them allocate 00061 * memory from the right place. To make sure that constructors/destructors 00062 * for arrays of objects allocated using placement new were called correctly, 00063 * Shankar et al had a hack using hash tables to maintain the number of 00064 * elements and call the destructors correctly. This hack was invoked using 00065 * -Wf,-Yv to the 5.3 compilers. 00066 * 00067 * This hack is gone in Mongoose. We therefore use the following scheme: 00068 * - instead of using placement new, we communicate with new using global 00069 * variables instead of parameters. As a result the standard C++ 00070 * implementation automatically counts the number of array elements, and 00071 * calls the constructor/destructor the correct number of times. 00072 * - we define the CXX_NEW and CXX_NEW_ARRAY macros to set the global 00073 * _dummy_new_mempool variable, and the new operator to MEM_POOL_Alloc 00074 * memory from this memory pool. Since CXX_NEW must be an expression, we 00075 * cannot have a scope within which to save the incoming value of this dummy, 00076 * and therefore there is a likelihood of this variable being overwritten 00077 * before it is used. Therefore the new operator resets this dummy to be -1 00078 * so that when the actual new comes around, it's value is gone, leading to 00079 * a compiler-runtime error. Thus CXX_NEWs cannot be nested. 00080 * Note that the last value in the expressions must be the return value 00081 * of the new operator, to have the types in the assignment x = CXX_NEW(...) 00082 * work out OK. 00083 * - we define the CXX_DELETE and CXX_DELETE_ARRAY macros to set the global 00084 * value of dummy_delete_mempool, which is used by the operator delete 00085 * to MEM_POOL_FREE the memory appropriately. Since CXX_DELETE is a 00086 * statement and not an expression, it can have a scope and save the 00087 * incoming value in a stack variable. So CXX_DELETEs can be nested. 00088 * - the final issue is to make sure that no one ever calls the original 00089 * new/delete operators -- this is arranged by exporting the new and delete 00090 * operators (__nw__FUi and __dl__FPv) in be/be/Exported. This overrides 00091 * calls to new and delete in libC from __vec_new, __vec_delete, etc. 00092 * 00093 * 00094 * 00095 * ABANDONED SCHEME: 00096 * ================= 00097 * 00098 * I experimented with another scheme in which I explicitly maintained the 00099 * number of elements of an array in 8 extra bytes of storage before the 00100 * pointer for all arrays. This scheme was abandoned since the above works 00101 * better, but here are some lessons learnt. The scheme was: 00102 * - try always using placement new, with the argument to new being the storage 00103 * allocated from MEM_POOL_Alloc. E.g. 00104 * #define CXX_NEW(type, pool) new (MEM_POOL_Alloc(sizeof(type), pool)) type 00105 * But this doesn't work since "type" might have arguments to the constructor 00106 * - so then we pass the memory pool as an argument to a placement new 00107 * operator that takes arguments. 00108 * #define CXX_NEW(constructor, mempool) (new (mempool) constructor) 00109 * - for arrays there are no arguments to constructors, so we allocate 00110 * 8 extra bytes, store the number of elements, and then call the above 00111 * new to allocate an array. Since it's placement new, the compiler does 00112 * nothing for arrays. 00113 * - for CXX_DELETE is easy - the operator delete is defined to do NOTHING. 00114 * the macro first calls the destructor, then calls MEM_POOL_FREE to free 00115 * the storage. 00116 * - for CXX_DELETE_ARRAY there is a loop -- look for the number of elements, 00117 * call the destructor for each element of the array, and then call 00118 * MEM_POOL_FREE. 00119 * 00120 * This scheme mostly worked. The problem came because the expansion of the 00121 * CXX_DELETE and CXX_DELETE_ARRAY macros contained the "pointer" argument 00122 * multiple times, and would therefore evaluate it repeatedly. So code like: 00123 * while (stack.Elements ()) 00124 * CXX_DELETE (stack.Pop ()); // or delete_array 00125 * did not work, since the stack.Pop would happen more than once, lots of 00126 * times. 00127 * The fix for this was to change the macro definition to also pass the 00128 * type in for the delete macros (at least for CXX_DELETE_ARRAY), but 00129 * thankfully we found the solution that we now use. Inline functions did 00130 * not work since we need a variable of the type being deleted, and we would 00131 * need an inline function for each type that we want to delete. 00132 * 00133 * The code for this abandoned scheme is in Rohit's workarea, in 00134 * /hosts/snowy.mti/work/workarea/v7.00/common/util/cxx_memory.{h,cxx}.shank 00135 */ 00136 00137 void* operator new (size_t sz) 00138 #if defined(__GNUC__) && (__GNUC__ < 3) 00139 throw(std::bad_alloc) 00140 #endif /* __GNUC__ */ 00141 { 00142 void* ptr; 00143 if (_dummy_new_mempool == (MEM_POOL*) -1) { 00144 DevWarn("new: _dummy_new_mempool is not yet set; Using Malloc_Mem_Pool"); 00145 _dummy_new_mempool = Malloc_Mem_Pool; 00146 } 00147 00148 ptr = (void *) MEM_POOL_Alloc_P(_dummy_new_mempool, 00149 sz+_dummy_pad, 00150 #ifdef Is_True_On 00151 _alloc_callsite_line, 00152 _alloc_callsite_file); 00153 _alloc_callsite_file = NULL; 00154 _alloc_callsite_line = 0; 00155 #else 00156 0, NULL); 00157 #endif 00158 _dummy_new_mempool = (MEM_POOL*) -1; 00159 _dummy_pad = 0; 00160 return ptr; 00161 } 00162 00163 void operator delete (void* ptr) 00164 #ifdef __GNUC__ 00165 throw() 00166 #endif /* __GNUC__ */ 00167 { 00168 if (_dummy_delete_mempool == (MEM_POOL*) -1) { 00169 DevWarn("new: _dummy_delete_mempool is not yet set; Using Malloc_Mem_Pool"); 00170 _dummy_delete_mempool = Malloc_Mem_Pool; 00171 } 00172 00173 MEM_POOL_FREE (_dummy_delete_mempool, ptr); 00174 _dummy_delete_mempool = (MEM_POOL*) -1; 00175 } 00176 00177 #ifdef __GNUC__ 00178 void operator delete[] (void* ptr) throw() { 00179 if (_dummy_delete_mempool == (MEM_POOL*) -1) { 00180 DevWarn("new: _dummy_delete_mempool is not yet set; Using Malloc_Mem_Pool"); 00181 _dummy_delete_mempool = Malloc_Mem_Pool; 00182 } 00183 00184 MEM_POOL_FREE (_dummy_delete_mempool, ptr); 00185 _dummy_delete_mempool = (MEM_POOL*) -1; 00186 } 00187 #endif 00188