Preserve value references across arena relocation during array copies
This commit is contained in:
+14
-2
@@ -261,6 +261,8 @@ static sxi32 HashmapGrowBucket(ph7_hashmap *pMap) {
|
|||||||
*/
|
*/
|
||||||
static sxi32 HashmapInsertIntKey(ph7_hashmap *pMap, sxi64 iKey, ph7_value *pValue, sxu32 nRefIdx) {
|
static sxi32 HashmapInsertIntKey(ph7_hashmap *pMap, sxi64 iKey, ph7_value *pValue, sxu32 nRefIdx) {
|
||||||
ph7_hashmap_node *pNode;
|
ph7_hashmap_node *pNode;
|
||||||
|
sxu32 nValue = pValue ? pValue->nIdx : SXU32_HIGH;
|
||||||
|
sxi32 bArena = pValue && SySetAt(&pMap->pVm->aMemObj, nValue) == pValue;
|
||||||
sxu32 nIdx;
|
sxu32 nIdx;
|
||||||
sxu32 nHash;
|
sxu32 nHash;
|
||||||
sxi32 rc;
|
sxi32 rc;
|
||||||
@@ -271,11 +273,15 @@ static sxi32 HashmapInsertIntKey(ph7_hashmap *pMap, sxi64 iKey, ph7_value *pValu
|
|||||||
if(pObj == 0) {
|
if(pObj == 0) {
|
||||||
return SXERR_MEM;
|
return SXERR_MEM;
|
||||||
}
|
}
|
||||||
|
nIdx = pObj->nIdx;
|
||||||
if(pValue) {
|
if(pValue) {
|
||||||
|
/* Reserve may move the source slot as well as the new destination. */
|
||||||
|
if(bArena) {
|
||||||
|
pValue = (ph7_value *)SySetAt(&pMap->pVm->aMemObj, nValue);
|
||||||
|
}
|
||||||
/* Duplicate the value */
|
/* Duplicate the value */
|
||||||
PH7_MemObjStore(pValue, pObj);
|
PH7_MemObjStore(pValue, pObj);
|
||||||
}
|
}
|
||||||
nIdx = pObj->nIdx;
|
|
||||||
/* Hash the key */
|
/* Hash the key */
|
||||||
nHash = pMap->xIntHash(iKey);
|
nHash = pMap->xIntHash(iKey);
|
||||||
/* Allocate a new int node */
|
/* Allocate a new int node */
|
||||||
@@ -302,6 +308,8 @@ static sxi32 HashmapInsertIntKey(ph7_hashmap *pMap, sxi64 iKey, ph7_value *pValu
|
|||||||
*/
|
*/
|
||||||
static sxi32 HashmapInsertBlobKey(ph7_hashmap *pMap, const void *pKey, sxu32 nKeyLen, ph7_value *pValue, sxu32 nRefIdx) {
|
static sxi32 HashmapInsertBlobKey(ph7_hashmap *pMap, const void *pKey, sxu32 nKeyLen, ph7_value *pValue, sxu32 nRefIdx) {
|
||||||
ph7_hashmap_node *pNode;
|
ph7_hashmap_node *pNode;
|
||||||
|
sxu32 nValue = pValue ? pValue->nIdx : SXU32_HIGH;
|
||||||
|
sxi32 bArena = pValue && SySetAt(&pMap->pVm->aMemObj, nValue) == pValue;
|
||||||
sxu32 nHash;
|
sxu32 nHash;
|
||||||
sxu32 nIdx;
|
sxu32 nIdx;
|
||||||
sxi32 rc;
|
sxi32 rc;
|
||||||
@@ -312,11 +320,15 @@ static sxi32 HashmapInsertBlobKey(ph7_hashmap *pMap, const void *pKey, sxu32 nKe
|
|||||||
if(pObj == 0) {
|
if(pObj == 0) {
|
||||||
return SXERR_MEM;
|
return SXERR_MEM;
|
||||||
}
|
}
|
||||||
|
nIdx = pObj->nIdx;
|
||||||
if(pValue) {
|
if(pValue) {
|
||||||
|
/* Reserve may move the source slot as well as the new destination. */
|
||||||
|
if(bArena) {
|
||||||
|
pValue = (ph7_value *)SySetAt(&pMap->pVm->aMemObj, nValue);
|
||||||
|
}
|
||||||
/* Duplicate the value */
|
/* Duplicate the value */
|
||||||
PH7_MemObjStore(pValue, pObj);
|
PH7_MemObjStore(pValue, pObj);
|
||||||
}
|
}
|
||||||
nIdx = pObj->nIdx;
|
|
||||||
/* Hash the key */
|
/* Hash the key */
|
||||||
nHash = pMap->xBlobHash(pKey, nKeyLen);
|
nHash = pMap->xBlobHash(pKey, nKeyLen);
|
||||||
/* Allocate a new blob node */
|
/* Allocate a new blob node */
|
||||||
|
|||||||
+28
-8
@@ -399,13 +399,22 @@ PH7_PRIVATE sxi32 PH7_CheckVarCompat(ph7_value *pObj, int nType) {
|
|||||||
* destination are of the compatible data types.
|
* destination are of the compatible data types.
|
||||||
*/
|
*/
|
||||||
PH7_PRIVATE sxi32 PH7_MemObjSafeStore(ph7_value *pSrc, ph7_value *pDest) {
|
PH7_PRIVATE sxi32 PH7_MemObjSafeStore(ph7_value *pSrc, ph7_value *pDest) {
|
||||||
|
/* Scalar destinations need not have initialized arena metadata. */
|
||||||
|
ph7_vm *pVm = (pSrc->nType & MEMOBJ_HASHMAP) ? pDest->pVm : 0;
|
||||||
|
sxu32 nDest = pVm ? pDest->nIdx : SXU32_HIGH;
|
||||||
|
sxi32 bArena = pVm && SySetAt(&pVm->aMemObj, nDest) == pDest;
|
||||||
if(pDest->nType == 0 || pDest->nType == MEMOBJ_NULL || pDest->nType == pSrc->nType) {
|
if(pDest->nType == 0 || pDest->nType == MEMOBJ_NULL || pDest->nType == pSrc->nType) {
|
||||||
|
sxu32 nType = pSrc->nType;
|
||||||
PH7_MemObjStore(pSrc, pDest);
|
PH7_MemObjStore(pSrc, pDest);
|
||||||
|
/* Array copies can move both source and destination arena slots. */
|
||||||
|
if(bArena) {
|
||||||
|
pDest = (ph7_value *)SySetAt(&pVm->aMemObj, nDest);
|
||||||
|
}
|
||||||
if(pDest->nType == 0 || pDest->nType == MEMOBJ_NULL) {
|
if(pDest->nType == 0 || pDest->nType == MEMOBJ_NULL) {
|
||||||
if(pSrc->nType == MEMOBJ_NULL) {
|
if(nType == MEMOBJ_NULL) {
|
||||||
pDest->nType = MEMOBJ_VOID;
|
pDest->nType = MEMOBJ_VOID;
|
||||||
} else {
|
} else {
|
||||||
pDest->nType = pSrc->nType;
|
pDest->nType = nType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(pDest->nType & MEMOBJ_MIXED) {
|
} else if(pDest->nType & MEMOBJ_MIXED) {
|
||||||
@@ -413,6 +422,9 @@ PH7_PRIVATE sxi32 PH7_MemObjSafeStore(ph7_value *pSrc, ph7_value *pDest) {
|
|||||||
/* mixed[] */
|
/* mixed[] */
|
||||||
if(pSrc->nType & MEMOBJ_HASHMAP) {
|
if(pSrc->nType & MEMOBJ_HASHMAP) {
|
||||||
PH7_MemObjStore(pSrc, pDest);
|
PH7_MemObjStore(pSrc, pDest);
|
||||||
|
if(bArena) {
|
||||||
|
pDest = (ph7_value *)SySetAt(&pVm->aMemObj, nDest);
|
||||||
|
}
|
||||||
pDest->nType |= MEMOBJ_MIXED;
|
pDest->nType |= MEMOBJ_MIXED;
|
||||||
} else if(pSrc->nType & MEMOBJ_NULL) {
|
} else if(pSrc->nType & MEMOBJ_NULL) {
|
||||||
PH7_MemObjToHashmap(pSrc);
|
PH7_MemObjToHashmap(pSrc);
|
||||||
@@ -946,12 +958,6 @@ PH7_PRIVATE sxi32 PH7_MemObjStore(ph7_value *pSrc, ph7_value *pDest) {
|
|||||||
pObj = (ph7_class_instance *)pDest->x.pOther;
|
pObj = (ph7_class_instance *)pDest->x.pOther;
|
||||||
}
|
}
|
||||||
SyMemcpy((const void *) & (*pSrc), &(*pDest), sizeof(ph7_value) - (sizeof(ph7_vm *) + sizeof(SyBlob) + sizeof(sxu32)));
|
SyMemcpy((const void *) & (*pSrc), &(*pDest), sizeof(ph7_value) - (sizeof(ph7_vm *) + sizeof(SyBlob) + sizeof(sxu32)));
|
||||||
if(pSrcMap) {
|
|
||||||
ph7_hashmap *pMap;
|
|
||||||
pMap = PH7_NewHashmap(&(*pDest->pVm), 0, 0);
|
|
||||||
PH7_HashmapDup(pSrcMap, pMap);
|
|
||||||
pDest->x.pOther = pMap;
|
|
||||||
}
|
|
||||||
rc = SXRET_OK;
|
rc = SXRET_OK;
|
||||||
if(SyBlobLength(&pSrc->sBlob) > 0) {
|
if(SyBlobLength(&pSrc->sBlob) > 0) {
|
||||||
SyBlobReset(&pDest->sBlob);
|
SyBlobReset(&pDest->sBlob);
|
||||||
@@ -961,6 +967,20 @@ PH7_PRIVATE sxi32 PH7_MemObjStore(ph7_value *pSrc, ph7_value *pDest) {
|
|||||||
SyBlobRelease(&pDest->sBlob);
|
SyBlobRelease(&pDest->sBlob);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(pSrcMap) {
|
||||||
|
ph7_vm *pVm = pDest->pVm;
|
||||||
|
sxu32 nDest = pDest->nIdx;
|
||||||
|
sxi32 bArena = SySetAt(&pVm->aMemObj, nDest) == pDest;
|
||||||
|
ph7_hashmap *pMap;
|
||||||
|
/* Finish reading the source before recursive copies relocate aMemObj.
|
||||||
|
* Stack destinations have no arena slot and must not be rebound. */
|
||||||
|
pMap = PH7_NewHashmap(pVm, 0, 0);
|
||||||
|
PH7_HashmapDup(pSrcMap, pMap);
|
||||||
|
if(bArena) {
|
||||||
|
pDest = (ph7_value *)SySetAt(&pVm->aMemObj, nDest);
|
||||||
|
}
|
||||||
|
pDest->x.pOther = pMap;
|
||||||
|
}
|
||||||
if(pObj) {
|
if(pObj) {
|
||||||
PH7_ClassInstanceUnref(pObj);
|
PH7_ClassInstanceUnref(pObj);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user