mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-05 08:10:05 +00:00
More performant OP_GETOBJECT & OP_SETOBJECT
constant indexes are now embedded in the instruction
This commit is contained in:
parent
ea4654cb6e
commit
c5bd0c2478
@ -127,9 +127,9 @@ int disasmInstr(CChunk *chunk, int offset, int indent) {
|
|||||||
case OP_NEWOBJECT:
|
case OP_NEWOBJECT:
|
||||||
return u16OperandInstruction("OP_NEWOBJECT", chunk, offset);
|
return u16OperandInstruction("OP_NEWOBJECT", chunk, offset);
|
||||||
case OP_GETOBJECT:
|
case OP_GETOBJECT:
|
||||||
return simpleInstruction("OP_GETOBJECT", offset);
|
return constInstruction("OP_GETOBJECT", chunk, offset);
|
||||||
case OP_SETOBJECT:
|
case OP_SETOBJECT:
|
||||||
return simpleInstruction("OP_SETOBJECT", offset);
|
return constInstruction("OP_SETOBJECT", chunk, offset);
|
||||||
case OP_INVOKE:
|
case OP_INVOKE:
|
||||||
return u8u8OperandInstruction("OP_INVOKE", chunk, offset);
|
return u8u8OperandInstruction("OP_INVOKE", chunk, offset);
|
||||||
case OP_ITER:
|
case OP_ITER:
|
||||||
|
17
src/cparse.c
17
src/cparse.c
@ -653,11 +653,11 @@ static void dot(CParseState *pstate, bool canAssign, Precedence prec) {
|
|||||||
uint16_t name = identifierConstant(pstate, &pstate->previous);
|
uint16_t name = identifierConstant(pstate, &pstate->previous);
|
||||||
|
|
||||||
if (canAssign && match(pstate, TOKEN_EQUAL)) {
|
if (canAssign && match(pstate, TOKEN_EQUAL)) {
|
||||||
writeu8(pstate, OP_LOADCONST);
|
|
||||||
writeu16(pstate, name);
|
|
||||||
expression(pstate, 1, true);
|
expression(pstate, 1, true);
|
||||||
|
|
||||||
writeu8(pstate, OP_SETOBJECT);
|
writeu8(pstate, OP_SETOBJECT);
|
||||||
valuePopped(pstate, 2); // pops key, value & object
|
writeu16(pstate, name);
|
||||||
|
valuePopped(pstate, 2); // value & object
|
||||||
} else if (match(pstate, TOKEN_PLUS_PLUS)) { // increment the field
|
} else if (match(pstate, TOKEN_PLUS_PLUS)) { // increment the field
|
||||||
writeu8(pstate, OP_INCOBJECT);
|
writeu8(pstate, OP_INCOBJECT);
|
||||||
writeu8(pstate, 128 + 1);
|
writeu8(pstate, 128 + 1);
|
||||||
@ -676,9 +676,8 @@ static void dot(CParseState *pstate, bool canAssign, Precedence prec) {
|
|||||||
valuePopped(pstate, args+1); // args + function
|
valuePopped(pstate, args+1); // args + function
|
||||||
valuePushed(pstate, pstate->compiler->expectedValues);
|
valuePushed(pstate, pstate->compiler->expectedValues);
|
||||||
} else {
|
} else {
|
||||||
writeu8(pstate, OP_LOADCONST);
|
|
||||||
writeu16(pstate, name);
|
|
||||||
writeu8(pstate, OP_GETOBJECT);
|
writeu8(pstate, OP_GETOBJECT);
|
||||||
|
writeu16(pstate, name);
|
||||||
// pops key & object but also pushes the field so total popped is 1
|
// pops key & object but also pushes the field so total popped is 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -705,6 +704,7 @@ static void _index(CParseState *pstate, bool canAssign, Precedence prec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ++test.field[1]
|
// ++test.field[1]
|
||||||
|
// this function is kind of spaghetti, feel free to rewrite (if you dare!)
|
||||||
static void walkIndexes(CParseState *pstate, int lastIndexType, uint16_t lastIdent, int val) {
|
static void walkIndexes(CParseState *pstate, int lastIndexType, uint16_t lastIdent, int val) {
|
||||||
uint16_t ident = lastIdent;
|
uint16_t ident = lastIdent;
|
||||||
int indexType = lastIndexType;
|
int indexType = lastIndexType;
|
||||||
@ -721,9 +721,8 @@ static void walkIndexes(CParseState *pstate, int lastIndexType, uint16_t lastIde
|
|||||||
|
|
||||||
switch (lastIndexType) {
|
switch (lastIndexType) {
|
||||||
case 0: // .
|
case 0: // .
|
||||||
writeu8(pstate, OP_LOADCONST); // pushes ident to stack
|
|
||||||
writeu16(pstate, lastIdent);
|
|
||||||
writeu8(pstate, OP_GETOBJECT); // grabs property
|
writeu8(pstate, OP_GETOBJECT); // grabs property
|
||||||
|
writeu16(pstate, lastIdent);
|
||||||
break;
|
break;
|
||||||
case 1: // []
|
case 1: // []
|
||||||
writeu8(pstate, OP_INDEX); // so, that was a normal index, perform that
|
writeu8(pstate, OP_INDEX); // so, that was a normal index, perform that
|
||||||
@ -1279,7 +1278,7 @@ static void forEachLoop(CParseState *pstate) {
|
|||||||
|
|
||||||
consume(pstate, TOKEN_DO, "Expected 'do' before loop block!");
|
consume(pstate, TOKEN_DO, "Expected 'do' before loop block!");
|
||||||
|
|
||||||
writeu8(pstate, OP_ITER); // checks if stack[top] is iterable and pushes the __next method onto the stack for OP_NEXT to call
|
writeu8(pstate, OP_ITER); // checks if stack[top] is iterable and pushes the __next metamethod onto the stack for OP_NEXT to call
|
||||||
|
|
||||||
// start loop scope
|
// start loop scope
|
||||||
LoopState cachedLoop = pstate->compiler->loop;
|
LoopState cachedLoop = pstate->compiler->loop;
|
||||||
@ -1434,6 +1433,7 @@ static int expressionPrecedence(CParseState *pstate, int needed, Precedence prec
|
|||||||
|
|
||||||
parsePrecedence(pstate, prec);
|
parsePrecedence(pstate, prec);
|
||||||
|
|
||||||
|
// make sure we're returning with the expected values they needed on the stack
|
||||||
if (pstate->compiler->pushedValues > saved) {
|
if (pstate->compiler->pushedValues > saved) {
|
||||||
writePop(pstate, pstate->compiler->pushedValues - saved);
|
writePop(pstate, pstate->compiler->pushedValues - saved);
|
||||||
valuePopped(pstate, pstate->compiler->pushedValues - saved);
|
valuePopped(pstate, pstate->compiler->pushedValues - saved);
|
||||||
@ -1442,7 +1442,6 @@ static int expressionPrecedence(CParseState *pstate, int needed, Precedence prec
|
|||||||
}
|
}
|
||||||
|
|
||||||
pstate->compiler->expectedValues = lastExpected;
|
pstate->compiler->expectedValues = lastExpected;
|
||||||
|
|
||||||
return pstate->compiler->pushedValues - (saved - needed);
|
return pstate->compiler->pushedValues - (saved - needed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,14 +185,16 @@ COSMO_API CValue* cosmoT_insert(CState *state, CTable *tbl, CValue key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool cosmoT_get(CTable *tbl, CValue key, CValue *val) {
|
bool cosmoT_get(CTable *tbl, CValue key, CValue *val) {
|
||||||
|
// sanity check
|
||||||
if (tbl->count == 0) {
|
if (tbl->count == 0) {
|
||||||
*val = cosmoV_newNil();
|
*val = cosmoV_newNil();
|
||||||
return false; // sanity check
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CTableEntry *entry = findEntry(tbl->table, tbl->capacity - 1, key);
|
CTableEntry *entry = findEntry(tbl->table, tbl->capacity - 1, key);
|
||||||
*val = entry->val;
|
*val = entry->val;
|
||||||
|
|
||||||
|
// return if get was successful
|
||||||
return !(IS_NIL(entry->key));
|
return !(IS_NIL(entry->key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,11 +19,12 @@ typedef struct CTable {
|
|||||||
COSMO_API void cosmoT_initTable(CState *state, CTable *tbl, int startCap);
|
COSMO_API void cosmoT_initTable(CState *state, CTable *tbl, int startCap);
|
||||||
COSMO_API void cosmoT_clearTable(CState *state, CTable *tbl);
|
COSMO_API void cosmoT_clearTable(CState *state, CTable *tbl);
|
||||||
COSMO_API void cosmoT_addTable(CState *state, CTable *from, CTable *to);
|
COSMO_API void cosmoT_addTable(CState *state, CTable *from, CTable *to);
|
||||||
COSMO_API CValue *cosmoT_insert(CState *state, CTable *tbl, CValue key);
|
|
||||||
COSMO_API int cosmoT_count(CTable *tbl);
|
COSMO_API int cosmoT_count(CTable *tbl);
|
||||||
|
|
||||||
CObjString *cosmoT_lookupString(CTable *tbl, const char *str, int length, uint32_t hash);
|
|
||||||
bool cosmoT_checkShrink(CState *state, CTable *tbl);
|
bool cosmoT_checkShrink(CState *state, CTable *tbl);
|
||||||
|
|
||||||
|
CObjString *cosmoT_lookupString(CTable *tbl, const char *str, int length, uint32_t hash);
|
||||||
|
COSMO_API CValue *cosmoT_insert(CState *state, CTable *tbl, CValue key);
|
||||||
bool cosmoT_get(CTable *tbl, CValue key, CValue *val);
|
bool cosmoT_get(CTable *tbl, CValue key, CValue *val);
|
||||||
bool cosmoT_remove(CState *state, CTable *tbl, CValue key);
|
bool cosmoT_remove(CState *state, CTable *tbl, CValue key);
|
||||||
|
|
||||||
|
20
src/cvm.c
20
src/cvm.c
@ -680,8 +680,8 @@ int cosmoV_execute(CState *state) {
|
|||||||
}
|
}
|
||||||
case OP_GETOBJECT: {
|
case OP_GETOBJECT: {
|
||||||
CValue val; // to hold our value
|
CValue val; // to hold our value
|
||||||
StkPtr key = cosmoV_getTop(state, 0); // key should be the top of the stack
|
StkPtr temp = cosmoV_getTop(state, 0); // that should be the object
|
||||||
StkPtr temp = cosmoV_getTop(state, 1); // after that should be the object
|
uint16_t ident = READUINT(); // use for the key
|
||||||
|
|
||||||
// sanity check
|
// sanity check
|
||||||
if (IS_OBJ(*temp)) {
|
if (IS_OBJ(*temp)) {
|
||||||
@ -689,13 +689,13 @@ int cosmoV_execute(CState *state) {
|
|||||||
case COBJ_DICT: { // syntax sugar, makes "namespaces" possible
|
case COBJ_DICT: { // syntax sugar, makes "namespaces" possible
|
||||||
CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp);
|
CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp);
|
||||||
|
|
||||||
cosmoT_get(&dict->tbl, *key, &val);
|
cosmoT_get(&dict->tbl, constants[ident], &val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case COBJ_OBJECT: {
|
case COBJ_OBJECT: {
|
||||||
CObjObject *object = (CObjObject*)cosmoV_readObj(*temp);
|
CObjObject *object = (CObjObject*)cosmoV_readObj(*temp);
|
||||||
|
|
||||||
cosmoV_getObject(state, object, *key, &val);
|
cosmoV_getObject(state, object, constants[ident], &val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -707,21 +707,21 @@ int cosmoV_execute(CState *state) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cosmoV_setTop(state, 2); // pops the object & the key
|
cosmoV_setTop(state, 1); // pops the object
|
||||||
cosmoV_pushValue(state, val); // pushes the field result
|
cosmoV_pushValue(state, val); // pushes the field result
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_SETOBJECT: {
|
case OP_SETOBJECT: {
|
||||||
StkPtr value = cosmoV_getTop(state, 0); // value is at the top of the stack
|
StkPtr value = cosmoV_getTop(state, 0); // value is at the top of the stack
|
||||||
StkPtr key = cosmoV_getTop(state, 1);
|
StkPtr temp = cosmoV_getTop(state, 1); // object is after the value
|
||||||
StkPtr temp = cosmoV_getTop(state, 2); // object is after the key
|
uint16_t ident = READUINT(); // use for the key
|
||||||
|
|
||||||
// sanity check
|
// sanity check
|
||||||
if (IS_OBJ(*temp)) {
|
if (IS_OBJ(*temp)) {
|
||||||
switch (cosmoV_readObj(*temp)->type) {
|
switch (cosmoV_readObj(*temp)->type) {
|
||||||
case COBJ_DICT: { // index and set the table
|
case COBJ_DICT: { // index and set the table
|
||||||
CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp);
|
CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp);
|
||||||
CValue *newVal = cosmoT_insert(state, &dict->tbl, *key);
|
CValue *newVal = cosmoT_insert(state, &dict->tbl, constants[ident]);
|
||||||
|
|
||||||
*newVal = *value; // set the index
|
*newVal = *value; // set the index
|
||||||
break;
|
break;
|
||||||
@ -729,7 +729,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
case COBJ_OBJECT: {
|
case COBJ_OBJECT: {
|
||||||
CObjObject *object = (CObjObject*)cosmoV_readObj(*temp);
|
CObjObject *object = (CObjObject*)cosmoV_readObj(*temp);
|
||||||
|
|
||||||
cosmoO_setRawObject(state, object, *key, *value);
|
cosmoO_setRawObject(state, object, constants[ident], *value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -742,7 +742,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// pop everything off the stack
|
// pop everything off the stack
|
||||||
cosmoV_setTop(state, 3);
|
cosmoV_setTop(state, 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_INVOKE: { // this is an optimization made by the parser, instead of allocating a CObjMethod every time we want to invoke a method, we shrink it down into one minimal instruction!
|
case OP_INVOKE: { // this is an optimization made by the parser, instead of allocating a CObjMethod every time we want to invoke a method, we shrink it down into one minimal instruction!
|
||||||
|
Loading…
Reference in New Issue
Block a user