[Tarantool-patches] [PATCH v4 13/53] sql: introduce mem_copy_as_ephemeral()

imeevma at tarantool.org imeevma at tarantool.org
Tue Mar 23 12:35:22 MSK 2021


This patch intoduces mem_copy_as_ephemeral(). This function copies value
from source MEM to destination MEM. In case value is of string or binary
type and its allocation type is not static, it copied as value with
ephemeral allocation type.

Part of #5818
---
 src/box/sql/mem.c  | 58 ++++++++++++++++++++--------------------------
 src/box/sql/mem.h  | 15 ++++++------
 src/box/sql/vdbe.c | 10 ++++----
 3 files changed, 38 insertions(+), 45 deletions(-)

diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c
index f12441d7c..30c568970 100644
--- a/src/box/sql/mem.c
+++ b/src/box/sql/mem.c
@@ -289,6 +289,25 @@ mem_copy(struct Mem *to, const struct Mem *from)
 	return 0;
 }
 
+int
+mem_copy_as_ephemeral(struct Mem *to, const struct Mem *from)
+{
+	mem_clear(to);
+	to->u = from->u;
+	to->flags = from->flags;
+	to->subtype = from->subtype;
+	to->field_type = from->field_type;
+	to->n = from->n;
+	to->z = from->z;
+	if ((to->flags & (MEM_Str | MEM_Blob)) == 0)
+		return 0;
+	if ((to->flags & (MEM_Static | MEM_Ephem)) != 0)
+		return 0;
+	to->flags &= (MEM_Str | MEM_Blob | MEM_Term | MEM_Zero | MEM_Subtype);
+	to->flags |= MEM_Ephem;
+	return 0;
+}
+
 static inline bool
 mem_has_msgpack_subtype(struct Mem *mem)
 {
@@ -400,20 +419,6 @@ vdbeMemAddTerminator(Mem * pMem)
 	return 0;
 }
 
-/*
- * Make an shallow copy of pFrom into pTo.  Prior contents of
- * pTo are freed.  The pFrom->z field is not duplicated.  If
- * pFrom->z is used, then pTo->z points to the same thing as pFrom->z
- * and flags gets srcType (either MEM_Ephem or MEM_Static).
- */
-static SQL_NOINLINE void
-vdbeClrCopy(Mem * pTo, const Mem * pFrom, int eType)
-{
-	mem_clear(pTo);
-	assert(!VdbeMemDynamic(pTo));
-	sqlVdbeMemShallowCopy(pTo, pFrom, eType);
-}
-
 /*
  * Both *pMem1 and *pMem2 contain string values. Compare the two values
  * using the collation sequence pColl. As usual, return a negative , zero
@@ -593,9 +598,12 @@ sqlVdbeMemAboutToChange(Vdbe * pVdbe, Mem * pMem)
 	int i;
 	Mem *pX;
 	for (i = 0, pX = pVdbe->aMem; i < pVdbe->nMem; i++, pX++) {
-		if (pX->pScopyFrom == pMem) {
-			pX->flags |= MEM_Undefined;
-			pX->pScopyFrom = 0;
+		if ((pX->flags & (MEM_Blob | MEM_Str)) != 0 &&
+		    (pX->flags & (MEM_Ephem | MEM_Static)) == 0) {
+			if (pX->pScopyFrom == pMem) {
+				pX->flags |= MEM_Undefined;
+				pX->pScopyFrom = 0;
+			}
 		}
 	}
 	pMem->pScopyFrom = 0;
@@ -2025,22 +2033,6 @@ vdbe_mem_alloc_blob_region(struct Mem *vdbe_mem, uint32_t size)
 	return 0;
 }
 
-void
-sqlVdbeMemShallowCopy(Mem * pTo, const Mem * pFrom, int srcType)
-{
-	assert(pTo->db == pFrom->db);
-	if (VdbeMemDynamic(pTo)) {
-		vdbeClrCopy(pTo, pFrom, srcType);
-		return;
-	}
-	memcpy(pTo, pFrom, MEMCELLSIZE);
-	if ((pFrom->flags & MEM_Static) == 0) {
-		pTo->flags &= ~(MEM_Dyn | MEM_Static | MEM_Ephem);
-		assert(srcType == MEM_Ephem || srcType == MEM_Static);
-		pTo->flags |= srcType;
-	}
-}
-
 /*
  * Transfer the contents of pFrom to pTo. Any existing value in pTo is
  * freed. If pFrom contains ephemeral data, a copy is made.
diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h
index fb649891a..58220d215 100644
--- a/src/box/sql/mem.h
+++ b/src/box/sql/mem.h
@@ -81,12 +81,6 @@ struct Mem {
 #endif
 };
 
-/*
- * Size of struct Mem not including the Mem.zMalloc member or anything that
- * follows.
- */
-#define MEMCELLSIZE offsetof(Mem,zMalloc)
-
 bool
 mem_is_null(const struct Mem *mem);
 
@@ -177,6 +171,14 @@ mem_destroy(struct Mem *mem);
 int
 mem_copy(struct Mem *to, const struct Mem *from);
 
+/**
+ * Copy content of MEM from one MEM to another. In case source MEM contains
+ * string or binary and allocation type is not STATIC, this value is copied as
+ * value with ephemeral allocation type.
+ */
+int
+mem_copy_as_ephemeral(struct Mem *to, const struct Mem *from);
+
 /* One or more of the following flags are set to indicate the validOK
  * representations of the value stored in the Mem struct.
  *
@@ -493,7 +495,6 @@ mem_is_type_compatible(struct Mem *mem, enum field_type type);
 
 int
 vdbe_mem_alloc_blob_region(struct Mem *vdbe_mem, uint32_t size);
-void sqlVdbeMemShallowCopy(Mem *, const Mem *, int);
 void sqlVdbeMemMove(Mem *, Mem *);
 int sqlVdbeMemMakeWriteable(Mem *);
 
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 05e0f78c1..55083fb23 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -917,7 +917,7 @@ case OP_Variable: {            /* out2 */
 		goto too_big;
 	}
 	pOut = vdbe_prepare_null_out(p, pOp->p2);
-	sqlVdbeMemShallowCopy(pOut, pVar, MEM_Static);
+	mem_copy_as_ephemeral(pOut, pVar);
 	UPDATE_MAX_BLOBSIZE(pOut);
 	break;
 }
@@ -979,7 +979,7 @@ case OP_Copy: {
 	pOut = &aMem[pOp->p2];
 	assert(pOut!=pIn1);
 	while( 1) {
-		sqlVdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
+		mem_copy_as_ephemeral(pOut, pIn1);
 		Deephemeralize(pOut);
 #ifdef SQL_DEBUG
 		pOut->pScopyFrom = 0;
@@ -1009,7 +1009,7 @@ case OP_SCopy: {            /* out2 */
 	pIn1 = &aMem[pOp->p1];
 	pOut = &aMem[pOp->p2];
 	assert(pOut!=pIn1);
-	sqlVdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
+	mem_copy_as_ephemeral(pOut, pIn1);
 #ifdef SQL_DEBUG
 	if (pOut->pScopyFrom==0) pOut->pScopyFrom = pIn1;
 #endif
@@ -2295,7 +2295,7 @@ case OP_Column: {
 	if (mem_is_null(pDest) &&
 	    (uint32_t) p2  >= pC->field_ref.field_count &&
 	    default_val_mem != NULL) {
-		sqlVdbeMemShallowCopy(pDest, default_val_mem, MEM_Static);
+		mem_copy_as_ephemeral(pDest, default_val_mem);
 	}
 	pDest->field_type = field_type;
 op_column_out:
@@ -4473,7 +4473,7 @@ case OP_Param: {           /* out2 */
 	pOut = vdbe_prepare_null_out(p, pOp->p2);
 	pFrame = p->pFrame;
 	pIn = &pFrame->aMem[pOp->p1 + pFrame->aOp[pFrame->pc].p1];
-	sqlVdbeMemShallowCopy(pOut, pIn, MEM_Ephem);
+	mem_copy_as_ephemeral(pOut, pIn);
 	break;
 }
 
-- 
2.25.1



More information about the Tarantool-patches mailing list