comparison gen/passes/GarbageCollect2Stack.cpp @ 1317:4099548c80e0

Allocate objects on the stack if they (a) don't have a destructor, and (b) don't override the delete operator (on top of the regular conditions for stack allocation that also apply to arrays, structs, etc.). The "no destructor" clause is not strictly necessary, but calling them at the right time would be tricky to say the least; it would involve, among other things, "manually" inserting a try-finally block around anything that might throw exceptions not caught in the current function. Note: objects with custom new operators are automatically ignored because they don't use the regular allocation runtime call, so there's no need to pay special attention to them.
author Frits van Bommel <fvbommel wxs.nl>
date Sat, 09 May 2009 00:50:15 +0200
parents 8c65217be813
children c21a6654cce2
comparison
equal deleted inserted replaced
1316:8c65217be813 1317:4099548c80e0
178 } 178 }
179 179
180 return alloca; 180 return alloca;
181 } 181 }
182 }; 182 };
183
184 // FunctionInfo for _d_allocclass
185 class AllocClassFI : public FunctionInfo {
186 public:
187 virtual bool analyze(CallSite CS, const Analysis& A) {
188 // This call contains no TypeInfo parameter, so don't call the
189 // base class implementation here...
190 if (CS.arg_size() != 1)
191 return false;
192 Value* arg = CS.getArgument(0)->stripPointerCasts();
193 GlobalVariable* ClassInfo = dyn_cast<GlobalVariable>(arg);
194 if (!ClassInfo)
195 return false;
196
197 std::string metaname = CD_PREFIX;
198 metaname.append(ClassInfo->getNameStart(), ClassInfo->getNameEnd());
199
200 GlobalVariable* global = A.M.getGlobalVariable(metaname);
201 if (!global || !global->hasInitializer())
202 return false;
203
204 MDNode* node = dyn_cast<MDNode>(global->getInitializer());
205 if (!node || node->getNumOperands() != CD_NumFields)
206 return false;
207
208 // Inserting destructor calls is not implemented yet, so classes
209 // with destructors are ignored for now.
210 Constant* hasDestructor = dyn_cast<Constant>(node->getOperand(CD_Finalize));
211 // We can't stack-allocate if the class has a custom deallocator
212 // (Custom allocators don't get turned into this runtime call, so
213 // those can be ignored)
214 Constant* hasCustomDelete = dyn_cast<Constant>(node->getOperand(CD_CustomDelete));
215 if (hasDestructor == NULL || hasCustomDelete == NULL)
216 return false;
217
218 if (ConstantExpr::getOr(hasDestructor, hasCustomDelete)
219 != ConstantInt::getFalse())
220 return false;
221
222 Ty = node->getOperand(CD_BodyType)->getType();
223 return true;
224 }
225
226 // The default promote() should be fine.
227
228 AllocClassFI() : FunctionInfo(-1, true) {}
229 };
183 } 230 }
184 231
185 232
186 //===----------------------------------------------------------------------===// 233 //===----------------------------------------------------------------------===//
187 // GarbageCollect2Stack Pass Implementation 234 // GarbageCollect2Stack Pass Implementation
195 Module* M; 242 Module* M;
196 243
197 FunctionInfo AllocMemoryT; 244 FunctionInfo AllocMemoryT;
198 ArrayFI NewArrayVT; 245 ArrayFI NewArrayVT;
199 ArrayFI NewArrayT; 246 ArrayFI NewArrayT;
247 AllocClassFI AllocClass;
200 248
201 public: 249 public:
202 static char ID; // Pass identification 250 static char ID; // Pass identification
203 GarbageCollect2Stack(); 251 GarbageCollect2Stack();
204 252
231 NewArrayT(0, true, true, 1) 279 NewArrayT(0, true, true, 1)
232 { 280 {
233 KnownFunctions["_d_allocmemoryT"] = &AllocMemoryT; 281 KnownFunctions["_d_allocmemoryT"] = &AllocMemoryT;
234 KnownFunctions["_d_newarrayvT"] = &NewArrayVT; 282 KnownFunctions["_d_newarrayvT"] = &NewArrayVT;
235 KnownFunctions["_d_newarrayT"] = &NewArrayT; 283 KnownFunctions["_d_newarrayT"] = &NewArrayT;
284 KnownFunctions["_d_allocclass"] = &AllocClass;
236 } 285 }
237 286
238 static void RemoveCall(Instruction* Inst) { 287 static void RemoveCall(Instruction* Inst) {
239 if (InvokeInst* Invoke = dyn_cast<InvokeInst>(Inst)) { 288 if (InvokeInst* Invoke = dyn_cast<InvokeInst>(Inst)) {
240 // If this was an invoke instruction, we need to do some extra 289 // If this was an invoke instruction, we need to do some extra