<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>On Apr 3, 2008, at 8:39 AM, Sam Bishop wrote:</div><div><div><br class="Apple-interchange-newline"><blockquote type="cite">Sam Bishop wrote:<br><blockquote type="cite">+TranslationUnit::~TranslationUnit() {<br></blockquote><blockquote type="cite">+  for (iterator I=begin(), E=end(); I!=E; ++I)<br></blockquote><blockquote type="cite">+    delete *I;<br></blockquote><blockquote type="cite">+}<br></blockquote><br>Meh.  I'm already over my head...<br><br>I expect that we would like serializing to be transparent.  In other<br>words, a new decl and a deserialized decl ought to be equivalent.<br><br>Decls are usually created using Create() calls, which takes a pointer to<br>an ASTContext object.  The deserialization code can't use those Create()<br>calls, because it's generic LLVM code which doesn't know anything about<br>the ASTContext class.<br><br>The reason that's a problem is because the ASTContext object determines<br>the allocator to use, at least in the "from source code" case. <br>Currently, the allocator is llvm::MallocAllocator, but the<br>deserialization code uses new.<br><br>Any suggestions?  "Here's a simpler project for you..." would work.  ;) <br>But I think that once I'm over this hump I can get back to trivial<br>additions of deletes and destructors...<br></blockquote><br></div><div>Hi Sam,</div><div><br></div><div>Right now all Decls are deserialized using a combination of </div><div><br></div><div><div>  static Decl* Create(llvm::Deserializer& D);   (from "Decl")</div><div><br></div><div>and implementation methods, e.g.:</div><div><br></div><div><div>  /// CreateImpl - Deserialize a BlockVarDecl.  Called by Decl::Create.</div> <div>  static BlockVarDecl* CreateImpl(llvm::Deserializer& D);  </div><div><br></div><div>Conceptually we could easily replace these with:</div><div><br></div><div><div>  static Decl* Create(llvm::Deserializer& D, Allocator& A);</div><div>  static BlockVarDecl* CreateImpl(llvm::Deserializer& D, Allocator &A); </div></div></div> <br></div><div>To get this to work with the Serialization library, we simply need to add a few more member templates to Deserializer to handle an extra argument to pass to the "Create" methods.  For example, here is the current implementation of Deserializer::ReadOwnedPtr from Deserialize.h (in the llvm tree):</div><div><br></div><div><div>  template <typename T></div> <div>  inline T* ReadOwnedPtr(bool AutoRegister = true) {</div> <div>    SerializedPtrID PtrID = ReadPtrID();    </div> <div><br></div> <div>    if (!PtrID)</div> <div>      return NULL;</div> <div>    </div> <div>    T* x = SerializeTrait<T>::Create(*this);</div> <div><br></div> <div>    if (AutoRegister)</div> <div>      RegisterPtr(PtrID,x);</div> <div>    </div> <div>    return x;</div> <div>  }</div><div><br></div><div>We can simply have a second version of this in Deserialize.h that accepts a second template argument:</div><div><br></div><div><div>  template <typename T, <b>typename Arg1</b>></div><div>  inline T* ReadOwnedPtr(<b>Arg1& arg1</b>, bool AutoRegister = true) {</div><div>    SerializedPtrID PtrID = ReadPtrID();    </div><div><br></div><div>    if (!PtrID)</div><div>      return NULL;</div><div>    </div><div>    T* x = SerializeTrait<T>::Create(*this, <b>arg1</b>);</div><div><br></div><div>    if (AutoRegister)</div><div>      RegisterPtr(PtrID,x);</div><div>    </div><div>    return x;</div><div>  }</div></div><div><br></div><div>We would also need to do this for all versions BatchReadOwnedPtrs that we also wanted to use in this way.</div><div><br></div><div>Finally, we would need to extend the default implementation of SerializeTrait<> (defined in Serialization.h).  Right now it is defined as:</div><div><br></div><div>template <typename T></div><div> <div>struct SerializeTrait {</div> <div>  static inline void Emit(Serializer& S, const T& X) { X.Emit(S); }</div> <div>  static inline void Read(Deserializer& D, T& X) { X.Read(D); }</div> <div>  static inline T* Create(Deserializer& D) { return T::Create(D); }</div> <div>};</div><div><br></div><div>We would just need to make a member template version of "Create":</div><div><br></div><div><div>template <typename T></div> <div>struct SerializeTrait {</div> <div>  static inline void Emit(Serializer& S, const T& X) { X.Emit(S); }</div> <div>  static inline void Read(Deserializer& D, T& X) { X.Read(D); }</div> <div><br></div><div>  static inline T* Create(Deserializer& D) { return T::Create(D); }</div><div><br></div><div><b>  template <typename Arg1></b></div><div><b>  static inline T* Create(Deserializer& D, Arg1& arg1) { return T::Create(D, arg1); }</b></div> <div>};</div> <br></div><div>Because of the magic of template instantiation, only the methods that are used in SerializeTrait are instantiated, so it should all just magically work.</div><div><br></div><div>So I think the solution is not technically all that hard; it just requires some tedious engineering to make separate instances of all the mentioned methods (and to of course add the necessary "Allocator" argument to the Decl::Create methods, etc.).</div><div><br></div><div>I've gone and taken an initial step by adding the member template to SerializeTrait:</div><div><br></div><div>  <a href="http://llvm.org/viewvc/llvm-project?view=rev&revision=49169">http://llvm.org/viewvc/llvm-project?view=rev&revision=49169</a></div><div><br></div><div>I can also start gradually adding the support that I mentioned in the Serialization library but doing a few template functions, and potentially allowing others to implementing all the instances of BatchReadOwnedPtrs that we need.</div><div><br></div><div>Ted</div> </div><div><br></div></div></div></body></html>