Author: Timm Baeder
Date: 2025-08-02T14:47:49+02:00
New Revision: 41803a24140c3c53bbc82c7b61c7b196cf9d113a

URL: 
https://github.com/llvm/llvm-project/commit/41803a24140c3c53bbc82c7b61c7b196cf9d113a
DIFF: 
https://github.com/llvm/llvm-project/commit/41803a24140c3c53bbc82c7b61c7b196cf9d113a.diff

LOG: [clang][bytecode] Replace MoveFn With DtorFn + memcpy (#151717)

First, the old MoveFn was rather inefficient, since the dead data cannot
ever be accessed anyway.

Second, there was a problem where the only reason a block still had a
pointer to it (and thus was made into a DeadBlock instead of simply
being deallocated) as that a nested field in the block pointed to the
block itself.

Fix this by calling the dtor function unconditionally. If the block
*still* has pointers after that, we really need to create a DeadBlock
for it.

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/InterpState.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/InterpState.cpp 
b/clang/lib/AST/ByteCode/InterpState.cpp
index 30108475d7db0..32ad07bb55d45 100644
--- a/clang/lib/AST/ByteCode/InterpState.cpp
+++ b/clang/lib/AST/ByteCode/InterpState.cpp
@@ -77,27 +77,27 @@ void InterpState::deallocate(Block *B) {
   const Descriptor *Desc = B->getDescriptor();
   assert(Desc);
 
+  // The block might have a pointer saved in a field in its data
+  // that points to the block itself. We call the dtor first,
+  // which will destroy all the data but leave InlineDescriptors
+  // intact. If the block THEN still has pointers, we create a
+  // DeadBlock for it.
+  if (B->IsInitialized)
+    B->invokeDtor();
+
   if (B->hasPointers()) {
     size_t Size = B->getSize();
-
     // Allocate a new block, transferring over pointers.
     char *Memory =
         reinterpret_cast<char *>(std::malloc(sizeof(DeadBlock) + Size));
     auto *D = new (Memory) DeadBlock(DeadBlocks, B);
-    std::memset(D->B.rawData(), 0, D->B.getSize());
-
-    // Move data and metadata from the old block to the new (dead)block.
-    if (B->IsInitialized && Desc->MoveFn) {
-      Desc->MoveFn(B, B->data(), D->data(), Desc);
-      if (Desc->getMetadataSize() > 0)
-        std::memcpy(D->rawData(), B->rawData(), Desc->getMetadataSize());
-    }
+    // Since the block doesn't hold any actual data anymore, we can just
+    // memcpy() everything over.
+    std::memcpy(D->rawData(), B->rawData(), Desc->getAllocSize());
     D->B.IsInitialized = B->IsInitialized;
 
     // We moved the contents over to the DeadBlock.
     B->IsInitialized = false;
-  } else if (B->IsInitialized) {
-    B->invokeDtor();
   }
 }
 


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to