Browse Source

Get rid of dirty references. Return a reference & pass-by reference are still working.

pull/50/head
Rafal Kupiec 2 years ago
parent
commit
3f205c19ce
Signed by: belliash GPG Key ID: 4E829243E0CFE6B4
7 changed files with 55 additions and 563 deletions
  1. +0
    -35
      engine/compiler.c
  2. +38
    -195
      engine/hashmap.c
  3. +3
    -8
      engine/memobj.c
  4. +1
    -1
      engine/oop.c
  5. +0
    -9
      engine/parser.c
  6. +12
    -309
      engine/vm.c
  7. +1
    -6
      include/ph7int.h

+ 0
- 35
engine/compiler.c View File

@ -794,7 +794,6 @@ static sxi32 PH7_GenStateArrayNodeValidator(ph7_gen_state *pGen, ph7_expr_node *
PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag) {
sxi32(*xValidator)(ph7_gen_state *, ph7_expr_node *); /* Expression tree validator callback */
SyToken *pKey, *pCur;
sxi32 iEmitRef = 0;
sxi32 nPair = 0;
sxi32 iNest;
sxi32 rc;
@ -862,31 +861,12 @@ PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag) {
/* No available key,load NULL */
PH7_VmEmitInstr(pGen->pVm, 0, PH7_OP_LOADC, 0, 0 /* nil index */, 0, 0);
}
if(pCur->nType & PH7_TK_AMPER /*'&'*/) {
/* Insertion by reference, [i.e: $a = array(&$x);] */
xValidator = PH7_GenStateArrayNodeValidator; /* Only variable are allowed */
iEmitRef = 1;
pCur++; /* Jump the '&' token */
if(pCur >= pGen->pIn) {
/* Missing value */
rc = PH7_GenCompileError(&(*pGen), E_ERROR, pCur->nLine, "array(): Missing referenced variable");
if(rc == SXERR_ABORT) {
return SXERR_ABORT;
}
return SXRET_OK;
}
}
/* Compile indice value */
rc = PH7_GenStateCompileArrayEntry(&(*pGen), pCur, pGen->pIn, EXPR_FLAG_RDONLY_LOAD/*Do not create the variable if non-existent*/, xValidator);
if(rc == SXERR_ABORT) {
return SXERR_ABORT;
}
if(iEmitRef) {
/* Emit the load reference instruction */
PH7_VmEmitInstr(pGen->pVm, 0, PH7_OP_LOAD_REF, 0, 0, 0, 0);
}
xValidator = 0;
iEmitRef = 0;
nPair++;
}
/* Emit the load map instruction */
@ -5073,21 +5053,6 @@ static sxi32 PH7_GenStateEmitExprCode(
(void)PH7_VmPopInstr(pGen->pVm);
}
}
} else if(iVmOp == PH7_OP_STORE_REF) {
pInstr = PH7_VmPopInstr(pGen->pVm);
if(pInstr) {
if(pInstr->iOp == PH7_OP_LOAD_IDX) {
/* Array insertion by reference [i.e: $pArray[] =& $some_var; ]
* We have to convert the STORE_REF instruction into STORE_IDX_REF
*/
iVmOp = PH7_OP_STORE_IDX_REF;
iP1 = pInstr->iP1;
iP2 = pInstr->iP2;
p3 = pInstr->p3;
} else {
p3 = pInstr->p3;
}
}
}
}
if(iVmOp > 0) {


+ 38
- 195
engine/hashmap.c View File

@ -16,10 +16,6 @@
/* Allowed node types */
#define HASHMAP_INT_NODE 1 /* Node with an int [i.e: 64-bit integer] key */
#define HASHMAP_BLOB_NODE 2 /* Node with a string/BLOB key */
/* Node control flags */
#define HASHMAP_NODE_FOREIGN_OBJ 0x001 /* Node hold a reference to a foreign ph7_value
* [i.e: array(&var)/$a[] =& $var ]
*/
/*
* Default hash function for int [i.e; 64-bit integer] keys.
*/
@ -193,9 +189,7 @@ PH7_PRIVATE void PH7_HashmapUnlinkNode(ph7_hashmap_node *pNode, int bRestore) {
/* Remove the ph7_value associated with this node from the reference table */
PH7_VmRefObjRemove(pVm, pNode->nValIdx, 0, pNode);
/* Restore to the freelist */
if((pNode->iFlags & HASHMAP_NODE_FOREIGN_OBJ) == 0) {
PH7_VmUnsetMemObj(pVm, pNode->nValIdx, FALSE);
}
PH7_VmUnsetMemObj(pVm, pNode->nValIdx, FALSE);
}
if(pNode->iType == HASHMAP_BLOB_NODE) {
SyBlobRelease(&pNode->xKey.sKey);
@ -271,26 +265,22 @@ static sxi32 HashmapGrowBucket(ph7_hashmap *pMap) {
* Insert a 64-bit integer key and it's associated value (if any) in the given
* hashmap.
*/
static sxi32 HashmapInsertIntKey(ph7_hashmap *pMap, sxi64 iKey, ph7_value *pValue, sxu32 nRefIdx, int isForeign) {
static sxi32 HashmapInsertIntKey(ph7_hashmap *pMap, sxi64 iKey, ph7_value *pValue, sxu32 nRefIdx) {
ph7_hashmap_node *pNode;
sxu32 nIdx;
sxu32 nHash;
sxi32 rc;
if(!isForeign) {
ph7_value *pObj;
/* Reserve a ph7_value for the value */
pObj = PH7_ReserveMemObj(pMap->pVm);
if(pObj == 0) {
return SXERR_MEM;
}
if(pValue) {
/* Duplicate the value */
PH7_MemObjStore(pValue, pObj);
}
nIdx = pObj->nIdx;
} else {
nIdx = nRefIdx;
ph7_value *pObj;
/* Reserve a ph7_value for the value */
pObj = PH7_ReserveMemObj(pMap->pVm);
if(pObj == 0) {
return SXERR_MEM;
}
if(pValue) {
/* Duplicate the value */
PH7_MemObjStore(pValue, pObj);
}
nIdx = pObj->nIdx;
/* Hash the key */
nHash = pMap->xIntHash(iKey);
/* Allocate a new int node */
@ -298,10 +288,6 @@ static sxi32 HashmapInsertIntKey(ph7_hashmap *pMap, sxi64 iKey, ph7_value *pValu
if(pNode == 0) {
return SXERR_MEM;
}
if(isForeign) {
/* Mark as a foregin entry */
pNode->iFlags |= HASHMAP_NODE_FOREIGN_OBJ;
}
/* Make sure the bucket is big enough to hold the new entry */
rc = HashmapGrowBucket(&(*pMap));
if(rc != SXRET_OK) {
@ -319,26 +305,22 @@ static sxi32 HashmapInsertIntKey(ph7_hashmap *pMap, sxi64 iKey, ph7_value *pValu
* Insert a BLOB key and it's associated value (if any) in the given
* hashmap.
*/
static sxi32 HashmapInsertBlobKey(ph7_hashmap *pMap, const void *pKey, sxu32 nKeyLen, ph7_value *pValue, sxu32 nRefIdx, int isForeign) {
static sxi32 HashmapInsertBlobKey(ph7_hashmap *pMap, const void *pKey, sxu32 nKeyLen, ph7_value *pValue, sxu32 nRefIdx) {
ph7_hashmap_node *pNode;
sxu32 nHash;
sxu32 nIdx;
sxi32 rc;
if(!isForeign) {
ph7_value *pObj;
/* Reserve a ph7_value for the value */
pObj = PH7_ReserveMemObj(pMap->pVm);
if(pObj == 0) {
return SXERR_MEM;
}
if(pValue) {
/* Duplicate the value */
PH7_MemObjStore(pValue, pObj);
}
nIdx = pObj->nIdx;
} else {
nIdx = nRefIdx;
ph7_value *pObj;
/* Reserve a ph7_value for the value */
pObj = PH7_ReserveMemObj(pMap->pVm);
if(pObj == 0) {
return SXERR_MEM;
}
if(pValue) {
/* Duplicate the value */
PH7_MemObjStore(pValue, pObj);
}
nIdx = pObj->nIdx;
/* Hash the key */
nHash = pMap->xBlobHash(pKey, nKeyLen);
/* Allocate a new blob node */
@ -346,10 +328,6 @@ static sxi32 HashmapInsertBlobKey(ph7_hashmap *pMap, const void *pKey, sxu32 nKe
if(pNode == 0) {
return SXERR_MEM;
}
if(isForeign) {
/* Mark as a foregin entry */
pNode->iFlags |= HASHMAP_NODE_FOREIGN_OBJ;
}
/* Make sure the bucket is big enough to hold the new entry */
rc = HashmapGrowBucket(&(*pMap));
if(rc != SXRET_OK) {
@ -553,7 +531,7 @@ static sxi32 HashmapInsert(
return SXRET_OK;
}
/* Perform a blob-key insertion */
rc = HashmapInsertBlobKey(&(*pMap), SyBlobData(&pKey->sBlob), SyBlobLength(&pKey->sBlob), &(*pVal), 0, FALSE);
rc = HashmapInsertBlobKey(&(*pMap), SyBlobData(&pKey->sBlob), SyBlobLength(&pKey->sBlob), &(*pVal), 0);
return rc;
}
IntKey:
@ -577,7 +555,7 @@ IntKey:
return SXRET_OK;
}
/* Perform a 64-bit-int-key insertion */
rc = HashmapInsertIntKey(&(*pMap), pKey->x.iVal, &(*pVal), 0, FALSE);
rc = HashmapInsertIntKey(&(*pMap), pKey->x.iVal, &(*pVal), 0);
if(rc == SXRET_OK) {
if(pKey->x.iVal >= pMap->iNextIdx) {
/* Increment the automatic index */
@ -590,102 +568,7 @@ IntKey:
}
} else {
/* Assign an automatic index */
rc = HashmapInsertIntKey(&(*pMap), pMap->iNextIdx, &(*pVal), 0, FALSE);
if(rc == SXRET_OK) {
++pMap->iNextIdx;
}
}
/* Insertion result */
return rc;
}
/*
* Insert a given key and it's associated value (foreign index) in the given
* hashmap.
* This is insertion by reference so be careful to mark the node
* with the HASHMAP_NODE_FOREIGN_OBJ flag being set.
* The insertion by reference is triggered when the following
* expression is encountered.
* $var = 10;
* $a = array(&var);
* OR
* $a[] =& $var;
* That is,$var is a foreign ph7_value and the $a array have no control
* over it's contents.
* Note that the node that hold the foreign ph7_value is automatically
* removed when the foreign ph7_value is unset.
* Example:
* $var = 10;
* $a[] =& $var;
* echo count($a).PHP_EOL; //1
* //Unset the foreign ph7_value now
* unset($var);
* echo count($a); //0
* Note that this is a PH7 eXtension.
* Refer to the official documentation for more information.
* If a node with the given key already exists in the database
* then this function overwrite the old value.
*/
static sxi32 HashmapInsertByRef(
ph7_hashmap *pMap, /* Target hashmap */
ph7_value *pKey, /* Lookup key */
sxu32 nRefIdx /* Foreign ph7_value index */
) {
ph7_hashmap_node *pNode = 0;
sxi32 rc = SXRET_OK;
if(pKey && pKey->iFlags & (MEMOBJ_STRING | MEMOBJ_HASHMAP | MEMOBJ_OBJ | MEMOBJ_RES)) {
if((pKey->iFlags & MEMOBJ_STRING) == 0) {
/* Force a string cast */
PH7_MemObjToString(&(*pKey));
}
if(SyBlobLength(&pKey->sBlob) < 1 || HashmapIsIntKey(&pKey->sBlob)) {
if(SyBlobLength(&pKey->sBlob) < 1) {
/* Automatic index assign */
pKey = 0;
}
goto IntKey;
}
if(SXRET_OK == HashmapLookupBlobKey(&(*pMap), SyBlobData(&pKey->sBlob),
SyBlobLength(&pKey->sBlob), &pNode)) {
/* Overwrite */
PH7_VmRefObjRemove(pMap->pVm, pNode->nValIdx, 0, pNode);
pNode->nValIdx = nRefIdx;
/* Install in the reference table */
PH7_VmRefObjInstall(pMap->pVm, nRefIdx, 0, pNode, 0);
return SXRET_OK;
}
/* Perform a blob-key insertion */
rc = HashmapInsertBlobKey(&(*pMap), SyBlobData(&pKey->sBlob), SyBlobLength(&pKey->sBlob), 0, nRefIdx, TRUE);
return rc;
}
IntKey:
if(pKey) {
if((pKey->iFlags & MEMOBJ_INT) == 0) {
/* Force an integer cast */
PH7_MemObjToInteger(pKey);
}
if(SXRET_OK == HashmapLookupIntKey(&(*pMap), pKey->x.iVal, &pNode)) {
/* Overwrite */
PH7_VmRefObjRemove(pMap->pVm, pNode->nValIdx, 0, pNode);
pNode->nValIdx = nRefIdx;
/* Install in the reference table */
PH7_VmRefObjInstall(pMap->pVm, nRefIdx, 0, pNode, 0);
return SXRET_OK;
}
/* Perform a 64-bit-int-key insertion */
rc = HashmapInsertIntKey(&(*pMap), pKey->x.iVal, 0, nRefIdx, TRUE);
if(rc == SXRET_OK) {
if(pKey->x.iVal >= pMap->iNextIdx) {
/* Increment the automatic index */
pMap->iNextIdx = pKey->x.iVal + 1;
/* Make sure the automatic index is not reserved */
while(SXRET_OK == HashmapLookupIntKey(&(*pMap), pMap->iNextIdx, 0)) {
pMap->iNextIdx++;
}
}
}
} else {
/* Assign an automatic index */
rc = HashmapInsertIntKey(&(*pMap), pMap->iNextIdx, 0, nRefIdx, TRUE);
rc = HashmapInsertIntKey(&(*pMap), pMap->iNextIdx, &(*pVal), 0);
if(rc == SXRET_OK) {
++pMap->iNextIdx;
}
@ -693,6 +576,7 @@ IntKey:
/* Insertion result */
return rc;
}
/*
* Extract node value.
*/
@ -722,12 +606,12 @@ static sxi32 HashmapInsertNode(ph7_hashmap *pMap, ph7_hashmap_node *pNode, int b
/* Assign an automatic index */
rc = HashmapInsert(&(*pMap), 0, pObj);
} else {
rc = HashmapInsertIntKey(&(*pMap), pNode->xKey.iKey, pObj, 0, FALSE);
rc = HashmapInsertIntKey(&(*pMap), pNode->xKey.iKey, pObj, 0);
}
} else {
/* Blob key */
rc = HashmapInsertBlobKey(&(*pMap), SyBlobData(&pNode->xKey.sKey),
SyBlobLength(&pNode->xKey.sKey), pObj, 0, FALSE);
SyBlobLength(&pNode->xKey.sKey), pObj, 0);
}
return rc;
}
@ -821,8 +705,8 @@ static int HashmapFindValue(
pVal = HashmapExtractNodeValue(pEntry);
if(pVal) {
if((pVal->iFlags | pNeedle->iFlags) & MEMOBJ_NULL) {
sxi32 iF1 = pVal->iFlags & ~MEMOBJ_AUX;
sxi32 iF2 = pNeedle->iFlags & ~MEMOBJ_AUX;
sxi32 iF1 = pVal->iFlags;
sxi32 iF2 = pNeedle->iFlags;
if(iF1 == iF2) {
/* NULL values are equals */
if(ppNode) {
@ -1144,7 +1028,7 @@ PH7_PRIVATE sxi32 PH7_HashmapDup(ph7_hashmap *pSrc, ph7_hashmap *pDest) {
PH7_MemObjRelease(&sKey);
} else {
/* Int key insertion */
rc = HashmapInsertIntKey(&(*pDest), pEntry->xKey.iKey, pVal, 0, FALSE);
rc = HashmapInsertIntKey(&(*pDest), pEntry->xKey.iKey, pVal, 0);
}
if(rc != SXRET_OK) {
return rc;
@ -1214,7 +1098,7 @@ PH7_PRIVATE sxi32 PH7_HashmapUnion(ph7_hashmap *pLeft, ph7_hashmap *pRight) {
if(pObj) {
/* Perform the insertion */
rc = HashmapInsertBlobKey(&(*pLeft), SyBlobData(&pEntry->xKey.sKey), SyBlobLength(&pEntry->xKey.sKey),
pObj, 0, FALSE);
pObj, 0);
if(rc != SXRET_OK) {
return rc;
}
@ -1226,7 +1110,7 @@ PH7_PRIVATE sxi32 PH7_HashmapUnion(ph7_hashmap *pLeft, ph7_hashmap *pRight) {
pObj = HashmapExtractNodeValue(pEntry);
if(pObj) {
/* Perform the insertion */
rc = HashmapInsertIntKey(&(*pLeft), pEntry->xKey.iKey, pObj, 0, FALSE);
rc = HashmapInsertIntKey(&(*pLeft), pEntry->xKey.iKey, pObj, 0);
if(rc != SXRET_OK) {
return rc;
}
@ -1345,10 +1229,8 @@ PH7_PRIVATE sxi32 PH7_HashmapRelease(ph7_hashmap *pMap, int FreeDS) {
pNext = pEntry->pPrev; /* Reverse link */
/* Remove the reference from the foreign table */
PH7_VmRefObjRemove(pVm, pEntry->nValIdx, 0, pEntry);
if((pEntry->iFlags & HASHMAP_NODE_FOREIGN_OBJ) == 0) {
/* Restore the ph7_value to the free list */
PH7_VmUnsetMemObj(pVm, pEntry->nValIdx, FALSE);
}
/* Restore the ph7_value to the free list */
PH7_VmUnsetMemObj(pVm, pEntry->nValIdx, FALSE);
/* Release the node */
if(pEntry->iType == HASHMAP_BLOB_NODE) {
SyBlobRelease(&pEntry->xKey.sKey);
@ -1419,40 +1301,7 @@ PH7_PRIVATE sxi32 PH7_HashmapInsert(
) {
return HashmapInsert(&(*pMap), &(*pKey), &(*pVal));
}
/*
* Insert a given key and it's associated value (foreign index) in the given
* hashmap.
* This is insertion by reference so be careful to mark the node
* with the HASHMAP_NODE_FOREIGN_OBJ flag being set.
* The insertion by reference is triggered when the following
* expression is encountered.
* $var = 10;
* $a = array(&var);
* OR
* $a[] =& $var;
* That is,$var is a foreign ph7_value and the $a array have no control
* over it's contents.
* Note that the node that hold the foreign ph7_value is automatically
* removed when the foreign ph7_value is unset.
* Example:
* $var = 10;
* $a[] =& $var;
* echo count($a).PHP_EOL; //1
* //Unset the foreign ph7_value now
* unset($var);
* echo count($a); //0
* Note that this is a PH7 eXtension.
* Refer to the official documentation for more information.
* If a node with the given key already exists in the database
* then this function overwrite the old value.
*/
PH7_PRIVATE sxi32 PH7_HashmapInsertByRef(
ph7_hashmap *pMap, /* Target hashmap */
ph7_value *pKey, /* Lookup key */
sxu32 nRefIdx /* Foreign ph7_value index */
) {
return HashmapInsertByRef(&(*pMap), &(*pKey), nRefIdx);
}
/*
* Reset the node cursor of a given hashmap.
*/
@ -5500,7 +5349,6 @@ PH7_PRIVATE sxi32 PH7_HashmapDump(SyBlob *pOut, ph7_hashmap *pMap, int ShowType,
ph7_hashmap_node *pEntry;
ph7_value *pObj;
sxu32 n = 0;
int isRef;
sxi32 rc;
int i;
if(nDepth > 31) {
@ -5547,13 +5395,8 @@ PH7_PRIVATE sxi32 PH7_HashmapDump(SyBlob *pOut, ph7_hashmap *pMap, int ShowType,
#endif
/* Dump node value */
pObj = HashmapExtractNodeValue(pEntry);
isRef = 0;
if(pObj) {
if(pEntry->iFlags & HASHMAP_NODE_FOREIGN_OBJ) {
/* Referenced object */
isRef = 1;
}
rc = PH7_MemObjDump(&(*pOut), pObj, ShowType, nTab + 1, nDepth, isRef);
rc = PH7_MemObjDump(&(*pOut), pObj, ShowType, nTab + 1, nDepth);
if(rc == SXERR_LIMIT) {
break;
}


+ 3
- 8
engine/memobj.c View File

@ -812,7 +812,6 @@ PH7_PRIVATE sxi32 PH7_MemObjStore(ph7_value *pSrc, ph7_value *pDest) {
pObj = (ph7_class_instance *)pDest->x.pOther;
}
SyMemcpy((const void *) & (*pSrc), &(*pDest), sizeof(ph7_value) - (sizeof(ph7_vm *) + sizeof(SyBlob) + sizeof(sxu32)));
pDest->iFlags &= ~MEMOBJ_AUX;
rc = SXRET_OK;
if(SyBlobLength(&pSrc->sBlob) > 0) {
SyBlobReset(&pDest->sBlob);
@ -931,8 +930,8 @@ PH7_PRIVATE sxi32 PH7_MemObjCmp(ph7_value *pObj1, ph7_value *pObj2, int bStrict,
if(bStrict) {
sxi32 iF1, iF2;
/* Strict comparisons with === */
iF1 = pObj1->iFlags & ~MEMOBJ_AUX;
iF2 = pObj2->iFlags & ~MEMOBJ_AUX;
iF1 = pObj1->iFlags;
iF2 = pObj2->iFlags;
if(iF1 != iF2) {
/* Not of the same type */
return 1;
@ -1206,8 +1205,7 @@ PH7_PRIVATE sxi32 PH7_MemObjDump(
ph7_value *pObj, /* Dump this */
int ShowType, /* TRUE to output value type */
int nTab, /* # of Whitespace to insert */
int nDepth, /* Nesting level */
int isRef /* TRUE if referenced object */
int nDepth /* Nesting level */
) {
sxi32 rc = SXRET_OK;
const char *zType;
@ -1216,9 +1214,6 @@ PH7_PRIVATE sxi32 PH7_MemObjDump(
SyBlobAppend(&(*pOut), " ", sizeof(char));
}
if(ShowType) {
if(isRef) {
SyBlobAppend(&(*pOut), "&", sizeof(char));
}
/* Get value type first */
zType = PH7_MemObjTypeDump(pObj);
SyBlobAppend(&(*pOut), zType, SyStrlen(zType));


+ 1
- 1
engine/oop.c View File

@ -929,7 +929,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceDump(SyBlob *pOut, ph7_class_instance *pThis,
#else
SyBlobAppend(&(*pOut), "\n", sizeof(char));
#endif
rc = PH7_MemObjDump(&(*pOut), pValue, ShowType, nTab + 1, nDepth, 0);
rc = PH7_MemObjDump(&(*pOut), pValue, ShowType, nTab + 1, nDepth);
if(rc == SXERR_LIMIT) {
break;
}


+ 0
- 9
engine/parser.c View File

@ -209,8 +209,6 @@ static const ph7_expr_op aOpTable[] = {
{ {"!==", sizeof(char) * 3}, EXPR_OP_TNE, 11, EXPR_OP_NON_ASSOC, PH7_OP_TNE},
/* Precedence 12,left-associative */
{ {"&", sizeof(char)}, EXPR_OP_BAND, 12, EXPR_OP_ASSOC_LEFT, PH7_OP_BAND},
/* Precedence 12,left-associative */
{ {"=&", sizeof(char) * 2}, EXPR_OP_REF, 12, EXPR_OP_ASSOC_LEFT, PH7_OP_STORE_REF},
/* Binary operators */
/* Precedence 13,left-associative */
{ {"^", sizeof(char)}, EXPR_OP_XOR, 13, EXPR_OP_ASSOC_LEFT, PH7_OP_BXOR},
@ -859,13 +857,6 @@ static sxi32 ExprProcessFuncArguments(ph7_gen_state *pGen, ph7_expr_node *pOp, p
iCur++;
}
if(iCur > iNode) {
if(apNode[iNode] && (apNode[iNode]->pStart->nType & PH7_TK_AMPER /*'&'*/) && ((iCur - iNode) == 2)
&& apNode[iNode + 1]->xCode == PH7_CompileVariable) {
PH7_GenCompileError(&(*pGen), E_WARNING, apNode[iNode]->pStart->nLine,
"call-time pass-by-reference is deprecated");
ExprFreeTree(&(*pGen), apNode[iNode]);
apNode[iNode] = 0;
}
ExprMakeTree(&(*pGen), &apNode[iNode], iCur - iNode);
if(apNode[iNode]) {
/* Put a pointer to the root of the tree in the arguments set */


+ 12
- 309
engine/vm.c View File

@ -1324,24 +1324,6 @@ PH7_PRIVATE ph7_value *PH7_ReserveMemObj(ph7_vm *pVm) {
pObj->nIdx = nIdx;
return pObj;
}
/*
* Insert an entry by reference (not copy) in the given hashmap.
*/
static sxi32 VmHashmapRefInsert(
ph7_hashmap *pMap, /* Target hashmap */
const char *zKey, /* Entry key */
sxu32 nByte, /* Key length */
sxu32 nRefIdx /* Entry index in the object pool */
) {
ph7_value sKey;
sxi32 rc;
PH7_MemObjInitFromString(pMap->pVm, &sKey, 0);
PH7_MemObjStringAppend(&sKey, zKey, nByte);
/* Perform the insertion */
rc = PH7_HashmapInsertByRef(&(*pMap), &sKey, nRefIdx);
PH7_MemObjRelease(&sKey);
return rc;
}
/*
* Extract a variable value from the top active VM frame.
* Return a pointer to the variable value on success.
@ -2492,26 +2474,14 @@ static sxi32 VmByteCodeExec(
iFlags = pEntry[1].iFlags; /* Save the type of value */
/* Perform the insertion */
while(pEntry < pTos) {
if(pEntry[1].iFlags & MEMOBJ_REFERENCE) {
/* Insertion by reference */
PH7_HashmapInsertByRef(pMap,
(pEntry->iFlags & MEMOBJ_NULL) ? 0 /* Automatic index assign */ : pEntry,
(sxu32)pEntry[1].x.iVal
);
} else {
/* Standard insertion */
PH7_HashmapInsert(pMap,
(pEntry->iFlags & MEMOBJ_NULL) ? 0 /* Automatic index assign */ : pEntry,
&pEntry[1]
);
}
/* Standard insertion */
PH7_HashmapInsert(pMap,
(pEntry->iFlags & MEMOBJ_NULL) ? 0 /* Automatic index assign */ : pEntry,
&pEntry[1]
);
/* Set the proper type of array */
if((iFlags & MEMOBJ_MIXED) == 0) {
if(pEntry[1].iFlags & MEMOBJ_REFERENCE) {
pFlags = pEntry[1].iFlags ^ MEMOBJ_REFERENCE;
} else {
pFlags = pEntry[1].iFlags;
}
pFlags = pEntry[1].iFlags;
if(iFlags != pFlags && iFlags != (pFlags ^ MEMOBJ_HASHMAP)) {
iFlags = MEMOBJ_MIXED;
}
@ -2801,12 +2771,10 @@ static sxi32 VmByteCodeExec(
}
/*
* STORE_IDX: P1 * P3
* STORE_IDX_R: P1 * P3
*
* Perfrom a store operation an a hashmap entry.
*/
case PH7_OP_STORE_IDX:
case PH7_OP_STORE_IDX_REF: {
case PH7_OP_STORE_IDX: {
ph7_hashmap *pMap = 0; /* cc warning */
ph7_value *pKey;
sxu32 nIdx;
@ -2836,7 +2804,7 @@ static sxi32 VmByteCodeExec(
break;
}
/* Phase#1: Load the array */
if((pObj->iFlags & MEMOBJ_STRING) && (pInstr->iOp != PH7_OP_STORE_IDX_REF)) {
if(pObj->iFlags & MEMOBJ_STRING) {
VmPopOperand(&pTos, 1);
if((pTos->iFlags & MEMOBJ_STRING) == 0) {
/* Force a string cast */
@ -2880,12 +2848,7 @@ static sxi32 VmByteCodeExec(
}
VmPopOperand(&pTos, 1);
/* Phase#2: Perform the insertion */
if(pInstr->iOp == PH7_OP_STORE_IDX_REF && pTos->nIdx != SXU32_HIGH) {
/* Insertion by reference */
PH7_HashmapInsertByRef(pMap, pKey, pTos->nIdx);
} else {
PH7_HashmapInsert(pMap, pKey, pTos);
}
PH7_HashmapInsert(pMap, pKey, pTos);
if(pKey) {
PH7_MemObjRelease(pKey);
}
@ -3958,96 +3921,6 @@ static sxi32 VmByteCodeExec(
}
break;
}
/*
* OP_LOAD_REF * * *
* Push the index of a referenced object on the stack.
*/
case PH7_OP_LOAD_REF: {
sxu32 nIdx;
#ifdef UNTRUST
if(pTos < pStack) {
goto Abort;
}
#endif
/* Extract memory object index */
nIdx = pTos->nIdx;
if(nIdx != SXU32_HIGH /* Not a constant */) {
/* Nullify the object */
PH7_MemObjRelease(pTos);
/* Mark as constant and store the index on the top of the stack */
pTos->x.iVal = (sxi64)nIdx;
pTos->nIdx = SXU32_HIGH;
pTos->iFlags = MEMOBJ_INT | MEMOBJ_REFERENCE;
}
break;
}
/*
* OP_STORE_REF * * P3
* Perform an assignment operation by reference.
*/
case PH7_OP_STORE_REF: {
SyString sName = { 0, 0 };
SyHashEntry *pEntry;
sxu32 nIdx;
#ifdef UNTRUST
if(pTos < pStack) {
goto Abort;
}
#endif
if(pInstr->p3 == 0) {
char *zName;
/* Take the variable name from the Next on the stack */
if((pTos->iFlags & MEMOBJ_STRING) == 0) {
/* Force a string cast */
PH7_MemObjToString(pTos);
}
if(SyBlobLength(&pTos->sBlob) > 0) {
zName = SyMemBackendStrDup(&pVm->sAllocator,
(const char *)SyBlobData(&pTos->sBlob), SyBlobLength(&pTos->sBlob));
if(zName) {
SyStringInitFromBuf(&sName, zName, SyBlobLength(&pTos->sBlob));
}
}
PH7_MemObjRelease(pTos);
pTos--;
} else {
SyStringInitFromBuf(&sName, pInstr->p3, SyStrlen((const char *)pInstr->p3));
}
nIdx = pTos->nIdx;
if(nIdx == SXU32_HIGH) {
if((pTos->iFlags & (MEMOBJ_OBJ | MEMOBJ_HASHMAP | MEMOBJ_RES)) == 0) {
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR,
"Reference operator require a variable not a constant as it's right operand");
} else {
ph7_value *pObj;
/* Extract the desired variable and if not available dynamically create it */
pObj = VmExtractMemObj(&(*pVm), &sName, FALSE, TRUE);
if(pObj == 0) {
PH7_VmMemoryError(&(*pVm));
}
/* Perform the store operation */
PH7_MemObjStore(pTos, pObj);
pTos->nIdx = pObj->nIdx;
}
} else if(sName.nByte > 0) {
VmFrame *pFrame = pVm->pFrame;
while(pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION)) {
/* Safely ignore the exception frame */
pFrame = pFrame->pParent;
}
/* Query the local frame */
pEntry = SyHashGet(&pFrame->hVar, (const void *)sName.zString, sName.nByte);
if(pEntry) {
rc = SyHashInsert(&pFrame->hVar, (const void *)sName.zString, sName.nByte, SX_INT_TO_PTR(nIdx));
if(rc == SXRET_OK) {
PH7_VmRefObjInstall(&(*pVm), nIdx, SyHashLastEntry(&pFrame->hVar), 0, 0);
}
} else {
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Referenced variable name '%z' does not exists", &sName);
}
}
break;
}
/*
* OP_LOAD_EXCEPTION * P2 P3
* Push an exception in the corresponding container so that
@ -5668,9 +5541,6 @@ static const char *VmInstrToString(sxi32 nOp) {
case PH7_OP_STORE_IDX:
zOp = "STORE_IDX";
break;
case PH7_OP_STORE_IDX_REF:
zOp = "STORE_IDX_R";
break;
case PH7_OP_PULL:
zOp = "PULL";
break;
@ -5734,12 +5604,6 @@ static const char *VmInstrToString(sxi32 nOp) {
case PH7_OP_CONSUME:
zOp = "CONSUME";
break;
case PH7_OP_LOAD_REF:
zOp = "LOAD_REF";
break;
case PH7_OP_STORE_REF:
zOp = "STORE_REF";
break;
case PH7_OP_MEMBER:
zOp = "MEMBER";
break;
@ -5812,163 +5676,6 @@ PH7_PRIVATE void PH7_VmExpandConstantValue(ph7_value *pVal, void *pUserData) {
* Status:
* Stable.
*/
/*
* int func_num_args(void)
* Returns the number of arguments passed to the function.
* Parameters
* None.
* Return
* Total number of arguments passed into the current user-defined function
* or -1 if called from the globe scope.
*/
static int vm_builtin_func_num_args(ph7_context *pCtx, int nArg, ph7_value **apArg) {
VmFrame *pFrame;
ph7_vm *pVm;
/* Point to the target VM */
pVm = pCtx->pVm;
/* Current frame */
pFrame = pVm->pFrame;
while(pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION)) {
/* Safely ignore the exception frame */
pFrame = pFrame->pParent;
}
if(pFrame->pParent == 0) {
SXUNUSED(nArg);
SXUNUSED(apArg);
/* Global frame,return -1 */
ph7_result_int(pCtx, -1);
return SXRET_OK;
}
/* Total number of arguments passed to the enclosing function */
nArg = (int)SySetUsed(&pFrame->sArg);
ph7_result_int(pCtx, nArg);
return SXRET_OK;
}
/*
* value func_get_arg(int $arg_num)
* Return an item from the argument list.
* Parameters
* Argument number(index start from zero).
* Return
* Returns the specified argument or FALSE on error.
*/
static int vm_builtin_func_get_arg(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_value *pObj = 0;
VmSlot *pSlot = 0;
VmFrame *pFrame;
ph7_vm *pVm;
/* Point to the target VM */
pVm = pCtx->pVm;
/* Current frame */
pFrame = pVm->pFrame;
while(pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION)) {
/* Safely ignore the exception frame */
pFrame = pFrame->pParent;
}
/* Extract the desired index */
nArg = ph7_value_to_int(apArg[0]);
if(nArg < 0 || nArg >= (int)SySetUsed(&pFrame->sArg)) {
/* Invalid index,return FALSE */
ph7_result_bool(pCtx, 0);
return SXRET_OK;
}
/* Extract the desired argument */
if((pSlot = (VmSlot *)SySetAt(&pFrame->sArg, (sxu32)nArg)) != 0) {
if((pObj = (ph7_value *)SySetAt(&pVm->aMemObj, pSlot->nIdx)) != 0) {
/* Return the desired argument */
ph7_result_value(pCtx, (ph7_value *)pObj);
} else {
/* No such argument,return false */
ph7_result_bool(pCtx, 0);
}
} else {
/* CAN'T HAPPEN */
ph7_result_bool(pCtx, 0);
}
return SXRET_OK;
}
/*
* array func_get_args_byref(void)
* Returns an array comprising a function's argument list.
* Parameters
* None.
* Return
* Returns an array in which each element is a POINTER to the corresponding
* member of the current user-defined function's argument list.
* Otherwise FALSE is returned on failure.
* NOTE:
* Arguments are returned to the array by reference.
*/
static int vm_builtin_func_get_args_byref(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_value *pArray;
VmFrame *pFrame;
VmSlot *aSlot;
sxu32 n;
/* Point to the current frame */
pFrame = pCtx->pVm->pFrame;
while(pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION)) {
/* Safely ignore the exception frame */
pFrame = pFrame->pParent;
}
/* Create a new array */
pArray = ph7_context_new_array(pCtx);
if(pArray == 0) {
SXUNUSED(nArg); /* cc warning */
SXUNUSED(apArg);
ph7_result_bool(pCtx, 0);
return SXRET_OK;
}
/* Start filling the array with the given arguments (Pass by reference) */
aSlot = (VmSlot *)SySetBasePtr(&pFrame->sArg);
for(n = 0; n < SySetUsed(&pFrame->sArg) ; n++) {
PH7_HashmapInsertByRef((ph7_hashmap *)pArray->x.pOther, 0/*Automatic index assign*/, aSlot[n].nIdx);
}
/* Return the freshly created array */
ph7_result_value(pCtx, pArray);
return SXRET_OK;
}
/*
* array func_get_args(void)
* Returns an array comprising a copy of function's argument list.
* Parameters
* None.
* Return
* Returns an array in which each element is a copy of the corresponding
* member of the current user-defined function's argument list.
* Otherwise FALSE is returned on failure.
*/
static int vm_builtin_func_get_args(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_value *pObj = 0;
ph7_value *pArray;
VmFrame *pFrame;
VmSlot *aSlot;
sxu32 n;
/* Point to the current frame */
pFrame = pCtx->pVm->pFrame;
while(pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION)) {
/* Safely ignore the exception frame */
pFrame = pFrame->pParent;
}
/* Create a new array */
pArray = ph7_context_new_array(pCtx);
if(pArray == 0) {
SXUNUSED(nArg); /* cc warning */
SXUNUSED(apArg);
ph7_result_bool(pCtx, 0);
return SXRET_OK;
}
/* Start filling the array with the given arguments */
aSlot = (VmSlot *)SySetBasePtr(&pFrame->sArg);
for(n = 0; n < SySetUsed(&pFrame->sArg) ; n++) {
pObj = (ph7_value *)SySetAt(&pCtx->pVm->aMemObj, aSlot[n].nIdx);
if(pObj) {
ph7_array_add_elem(pArray, 0/* Automatic index assign*/, pObj);
}
}
/* Return the freshly created array */
ph7_result_value(pCtx, pArray);
return SXRET_OK;
}
/*
* bool function_exists(string $name)
* Return TRUE if the given function has been defined.
@ -8491,7 +8198,7 @@ static int vm_builtin_var_dump(ph7_context *pCtx, int nArg, ph7_value **apArg) {
/* Reset the working buffer */
SyBlobReset(&sDump);
/* Dump the given expression */
PH7_MemObjDump(&sDump, pObj, TRUE, 0, 0, 0);
PH7_MemObjDump(&sDump, pObj, TRUE, 0, 0);
/* Output */
if(SyBlobLength(&sDump) > 0) {
ph7_context_output(pCtx, (const char *)SyBlobData(&sDump), (int)SyBlobLength(&sDump));
@ -8527,7 +8234,7 @@ static int vm_builtin_print_r(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ret_string = ph7_value_to_bool(apArg[1]);
}
/* Generate dump */
PH7_MemObjDump(&sDump, apArg[0], FALSE, 0, 0, 0);
PH7_MemObjDump(&sDump, apArg[0], FALSE, 0, 0);
if(!ret_string) {
/* Output dump */
ph7_context_output(pCtx, (const char *)SyBlobData(&sDump), (int)SyBlobLength(&sDump));
@ -8559,7 +8266,7 @@ static int vm_builtin_var_export(ph7_context *pCtx, int nArg, ph7_value **apArg)
ret_string = ph7_value_to_bool(apArg[1]);
}
/* Generate dump */
PH7_MemObjDump(&sDump, apArg[0], FALSE, 0, 0, 0);
PH7_MemObjDump(&sDump, apArg[0], FALSE, 0, 0);
if(!ret_string) {
/* Output dump */
ph7_context_output(pCtx, (const char *)SyBlobData(&sDump), (int)SyBlobLength(&sDump));
@ -10841,10 +10548,6 @@ static int vm_builtin_utf8_decode(ph7_context *pCtx, int nArg, ph7_value **apArg
}
/* Table of built-in VM functions. */
static const ph7_builtin_func aVmFunc[] = {
{ "func_num_args", vm_builtin_func_num_args },
{ "func_get_arg", vm_builtin_func_get_arg },
{ "func_get_args", vm_builtin_func_get_args },
{ "func_get_args_byref", vm_builtin_func_get_args_byref },
{ "function_exists", vm_builtin_func_exists },
{ "is_callback", vm_builtin_is_callback },
{ "get_defined_functions", vm_builtin_get_defined_func },


+ 1
- 6
include/ph7int.h View File

@ -641,7 +641,6 @@ struct ph7_value {
#define MEMOBJ_STRING 0x0080 /* Memory value is a UTF-8 string */
#define MEMOBJ_VOID 0x0100 /* Memory value is a void */
#define MEMOBJ_MIXED 0x0200 /* Memory value is mixed */
#define MEMOBJ_REFERENCE 0x0400 /* Memory value hold a reference (64-bit index) of another ph7_value */
#define MEMOBJ_HASHMAP 0x0800 /* Memory value is a hashmap aka 'array' in the PHP jargon */
#define MEMOBJ_NULL 0x1000 /* Memory value is NULL */
/* Mask of all known types */
@ -652,7 +651,6 @@ struct ph7_value {
* Types array, object and resource are not scalar.
*/
#define MEMOBJ_SCALAR (MEMOBJ_STRING|MEMOBJ_INT|MEMOBJ_REAL|MEMOBJ_BOOL|MEMOBJ_CHAR|MEMOBJ_VOID|MEMOBJ_NULL)
#define MEMOBJ_AUX (MEMOBJ_REFERENCE)
/*
* The following macro clear the current ph7_value type and replace
* it with the given one.
@ -1453,8 +1451,6 @@ enum ph7_vm_op {
PH7_OP_BOR_STORE, /* Bitor and store '|=' */
PH7_OP_BXOR_STORE, /* Bitxor and store '^=' */
PH7_OP_CONSUME, /* Consume VM output */
PH7_OP_LOAD_REF, /* Load reference */
PH7_OP_STORE_REF, /* Store a reference to a variable*/
PH7_OP_MEMBER, /* Class member run-time access */
PH7_OP_CVT_OBJ, /* Object cast */
PH7_OP_CVT_CALL, /* Callback cast */
@ -1626,7 +1622,7 @@ enum json_err_code {
JSON_ERROR_UTF8 /* Malformed UTF-8 characters */
};
/* memobj.c function prototypes */
PH7_PRIVATE sxi32 PH7_MemObjDump(SyBlob *pOut, ph7_value *pObj, int ShowType, int nTab, int nDepth, int isRef);
PH7_PRIVATE sxi32 PH7_MemObjDump(SyBlob *pOut, ph7_value *pObj, int ShowType, int nTab, int nDepth);
PH7_PRIVATE const char *PH7_MemObjTypeDump(ph7_value *pVal);
PH7_PRIVATE sxi32 PH7_MemObjAdd(ph7_value *pObj1, ph7_value *pObj2, int bAddStore);
PH7_PRIVATE sxi32 PH7_MemObjCmp(ph7_value *pObj1, ph7_value *pObj2, int bStrict, int iNest);
@ -1739,7 +1735,6 @@ PH7_PRIVATE sxi32 PH7_HashmapRelease(ph7_hashmap *pMap, int FreeDS);
PH7_PRIVATE void PH7_HashmapUnref(ph7_hashmap *pMap);
PH7_PRIVATE sxi32 PH7_HashmapLookup(ph7_hashmap *pMap, ph7_value *pKey, ph7_hashmap_node **ppNode);
PH7_PRIVATE sxi32 PH7_HashmapInsert(ph7_hashmap *pMap, ph7_value *pKey, ph7_value *pVal);
PH7_PRIVATE sxi32 PH7_HashmapInsertByRef(ph7_hashmap *pMap, ph7_value *pKey, sxu32 nRefIdx);
PH7_PRIVATE sxi32 PH7_HashmapUnion(ph7_hashmap *pLeft, ph7_hashmap *pRight);
PH7_PRIVATE void PH7_HashmapUnlinkNode(ph7_hashmap_node *pNode, int bRestore);
PH7_PRIVATE sxi32 PH7_HashmapDup(ph7_hashmap *pSrc, ph7_hashmap *pDest);


Loading…
Cancel
Save