Skip to content

Commit

Permalink
Optimize ref count updates
Browse files Browse the repository at this point in the history
  • Loading branch information
vtereshkov authored Aug 5, 2024
1 parent b80ccc8 commit c6256a4
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 33 deletions.
2 changes: 1 addition & 1 deletion playground/umka.js

Large diffs are not rendered by default.

44 changes: 28 additions & 16 deletions src/umka_gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,14 +162,6 @@ static bool optimizePop(CodeGen *gen)
return true;
}

// Optimization: CHANGE_REF_CNT + POP -> CHANGE_REF_CNT; POP
if (prev && prev->opcode == OP_CHANGE_REF_CNT && prev->inlineOpcode == OP_NOP)
{
prev->inlineOpcode = OP_POP;
genUnnotify(gen);
return true;
}

return false;
}

Expand Down Expand Up @@ -583,7 +575,27 @@ void genChangeRefCnt(CodeGen *gen, TokenKind tokKind, Type *type)
{
if (typeGarbageCollected(type))
{
const Instruction instr = {.opcode = OP_CHANGE_REF_CNT, .tokKind = tokKind, .typeKind = TYPE_NONE, .operand.ptrVal = type};
const Instruction instr = {.opcode = OP_CHANGE_REF_CNT, .tokKind = tokKind, .type = type};
genAddInstr(gen, &instr);
}
}


void genChangeRefCntGlobal(CodeGen *gen, TokenKind tokKind, void *ptrVal, Type *type)
{
if (typeGarbageCollected(type))
{
const Instruction instr = {.opcode = OP_CHANGE_REF_CNT_GLOBAL, .tokKind = tokKind, .operand.ptrVal = ptrVal, .type = type};
genAddInstr(gen, &instr);
}
}


void genChangeRefCntLocal(CodeGen *gen, TokenKind tokKind, int offset, Type *type)
{
if (typeGarbageCollected(type))
{
const Instruction instr = {.opcode = OP_CHANGE_REF_CNT_LOCAL, .tokKind = tokKind, .operand.intVal = offset, .type = type};
genAddInstr(gen, &instr);
}
}
Expand All @@ -593,7 +605,7 @@ void genChangeRefCntAssign(CodeGen *gen, Type *type)
{
if (typeGarbageCollected(type))
{
const Instruction instr = {.opcode = OP_CHANGE_REF_CNT_ASSIGN, .tokKind = TOK_NONE, .typeKind = TYPE_NONE, .operand.ptrVal = type};
const Instruction instr = {.opcode = OP_CHANGE_REF_CNT_ASSIGN, .tokKind = TOK_NONE, .type = type};
genAddInstr(gen, &instr);
}
else
Expand All @@ -605,7 +617,7 @@ void genSwapChangeRefCntAssign(CodeGen *gen, Type *type)
{
if (typeGarbageCollected(type))
{
const Instruction instr = {.opcode = OP_CHANGE_REF_CNT_ASSIGN, .inlineOpcode = OP_SWAP, .tokKind = TOK_NONE, .typeKind = TYPE_NONE, .operand.ptrVal = type};
const Instruction instr = {.opcode = OP_CHANGE_REF_CNT_ASSIGN, .inlineOpcode = OP_SWAP, .tokKind = TOK_NONE, .type = type};
genAddInstr(gen, &instr);
}
else
Expand All @@ -617,7 +629,7 @@ void genChangeLeftRefCntAssign(CodeGen *gen, Type *type)
{
if (typeGarbageCollected(type))
{
const Instruction instr = {.opcode = OP_CHANGE_REF_CNT_ASSIGN, .tokKind = TOK_MINUSMINUS, .typeKind = TYPE_NONE, .operand.ptrVal = type};
const Instruction instr = {.opcode = OP_CHANGE_REF_CNT_ASSIGN, .tokKind = TOK_MINUSMINUS, .type = type};
genAddInstr(gen, &instr);
}
else
Expand Down Expand Up @@ -664,7 +676,7 @@ void genGetDynArrayPtr(CodeGen *gen)

void genGetMapPtr(CodeGen *gen, Type *mapType)
{
const Instruction instr = {.opcode = OP_GET_MAP_PTR, .tokKind = TOK_NONE, .typeKind = TYPE_NONE, .operand.ptrVal = mapType};
const Instruction instr = {.opcode = OP_GET_MAP_PTR, .tokKind = TOK_NONE, .type = mapType};
genAddInstr(gen, &instr);
}

Expand All @@ -681,7 +693,7 @@ void genGetFieldPtr(CodeGen *gen, int fieldOffset)

void genAssertType(CodeGen *gen, Type *type)
{
const Instruction instr = {.opcode = OP_ASSERT_TYPE, .tokKind = TOK_NONE, .typeKind = TYPE_NONE, .operand.ptrVal = type};
const Instruction instr = {.opcode = OP_ASSERT_TYPE, .tokKind = TOK_NONE, .type = type};
genAddInstr(gen, &instr);
}

Expand Down Expand Up @@ -768,14 +780,14 @@ void genReturn(CodeGen *gen, int paramSlots)

void genEnterFrame(CodeGen *gen, int localVarSlots)
{
const Instruction instr = {.opcode = OP_ENTER_FRAME, .tokKind = TOK_NONE, TYPE_NONE, .operand.intVal = localVarSlots};
const Instruction instr = {.opcode = OP_ENTER_FRAME, .tokKind = TOK_NONE, .typeKind = TYPE_NONE, .operand.intVal = localVarSlots};
genAddInstr(gen, &instr);
}


void genLeaveFrame(CodeGen *gen)
{
const Instruction instr = {.opcode = OP_LEAVE_FRAME, .tokKind = TOK_NONE, TYPE_NONE, .operand.intVal = 0};
const Instruction instr = {.opcode = OP_LEAVE_FRAME, .tokKind = TOK_NONE, .typeKind = TYPE_NONE, .operand.intVal = 0};
genAddInstr(gen, &instr);
}

Expand Down
2 changes: 2 additions & 0 deletions src/umka_gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ void genAssign (CodeGen *gen, TypeKind typeKind, int structSize);
void genSwapAssign (CodeGen *gen, TypeKind typeKind, int structSize);

void genChangeRefCnt (CodeGen *gen, TokenKind tokKind, Type *type);
void genChangeRefCntGlobal (CodeGen *gen, TokenKind tokKind, void *ptrVal, Type *type);
void genChangeRefCntLocal (CodeGen *gen, TokenKind tokKind, int offset, Type *type);
void genChangeRefCntAssign (CodeGen *gen, Type *type);
void genSwapChangeRefCntAssign (CodeGen *gen, Type *type);
void genChangeLeftRefCntAssign (CodeGen *gen, Type *type);
Expand Down
8 changes: 4 additions & 4 deletions src/umka_stmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ void doGarbageCollection(Compiler *comp, int block)
for (Ident *ident = comp->idents.first; ident; ident = ident->next)
if (ident->kind == IDENT_VAR && typeGarbageCollected(ident->type) && ident->block == block && !(ident->temporary && !ident->used) && strcmp(ident->name, "__result") != 0)
{
doPushVarPtr(comp, ident);
genDeref(&comp->gen, ident->type->kind);
genChangeRefCnt(&comp->gen, TOK_MINUSMINUS, ident->type);
genPop(&comp->gen);
if (ident->block == 0)
genChangeRefCntGlobal(&comp->gen, TOK_MINUSMINUS, ident->ptr, ident->type);
else
genChangeRefCntLocal(&comp->gen, TOK_MINUSMINUS, ident->offset, ident->type);
}
}

Expand Down
61 changes: 50 additions & 11 deletions src/umka_vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ static const char *opcodeSpelling [] =
"DEREF",
"ASSIGN",
"CHANGE_REF_CNT",
"CHANGE_REF_CNT_GLOBAL",
"CHANGE_REF_CNT_LOCAL",
"CHANGE_REF_CNT_ASSIGN",
"UNARY",
"BINARY",
Expand Down Expand Up @@ -2857,12 +2859,39 @@ static FORCE_INLINE void doChangeRefCnt(Fiber *fiber, HeapPages *pages)
{
void *ptr = fiber->top->ptrVal;
TokenKind tokKind = fiber->code[fiber->ip].tokKind;
Type *type = (Type *)fiber->code[fiber->ip].operand.ptrVal;
Type *type = fiber->code[fiber->ip].type;

doBasicChangeRefCnt(fiber, pages, ptr, type, tokKind);

if (fiber->code[fiber->ip].inlineOpcode == OP_POP)
fiber->top++;
fiber->ip++;
}


static FORCE_INLINE void doChangeRefCntGlobal(Fiber *fiber, HeapPages *pages, Error *error)
{
TokenKind tokKind = fiber->code[fiber->ip].tokKind;
Type *type = fiber->code[fiber->ip].type;
void *ptr = fiber->code[fiber->ip].operand.ptrVal;

Slot slot = {.ptrVal = ptr};

doBasicDeref(&slot, type->kind, error);
doBasicChangeRefCnt(fiber, pages, slot.ptrVal, type, tokKind);

fiber->ip++;
}


static FORCE_INLINE void doChangeRefCntLocal(Fiber *fiber, HeapPages *pages, Error *error)
{
TokenKind tokKind = fiber->code[fiber->ip].tokKind;
Type *type = fiber->code[fiber->ip].type;
int offset = fiber->code[fiber->ip].operand.intVal;

Slot slot = {.ptrVal = (int8_t *)fiber->base + offset};

doBasicDeref(&slot, type->kind, error);
doBasicChangeRefCnt(fiber, pages, slot.ptrVal, type, tokKind);

fiber->ip++;
}
Expand All @@ -2875,7 +2904,7 @@ static FORCE_INLINE void doChangeRefCntAssign(Fiber *fiber, HeapPages *pages, Er

Slot rhs = *fiber->top++;
void *lhs = (fiber->top++)->ptrVal;
Type *type = (Type *)fiber->code[fiber->ip].operand.ptrVal;
Type *type = fiber->code[fiber->ip].type;

// Increase right-hand side ref count
if (fiber->code[fiber->ip].tokKind != TOK_MINUSMINUS) // "--" means that the right-hand side ref count should not be increased
Expand Down Expand Up @@ -3204,8 +3233,7 @@ static FORCE_INLINE void doGetMapPtr(Fiber *fiber, HeapPages *pages, Error *erro
{
Slot key = *fiber->top++;
Map *map = (Map *)(fiber->top++)->ptrVal;

Type *mapType = (Type *)fiber->code[fiber->ip].operand.ptrVal;
Type *mapType = fiber->code[fiber->ip].type;

if (!map)
error->runtimeHandler(error->context, VM_RUNTIME_ERROR, "Map is null");
Expand Down Expand Up @@ -3255,7 +3283,7 @@ static FORCE_INLINE void doGetFieldPtr(Fiber *fiber, Error *error)
static FORCE_INLINE void doAssertType(Fiber *fiber)
{
Interface *interface = (Interface *)(fiber->top++)->ptrVal;
Type *type = (Type *)fiber->code[fiber->ip].operand.ptrVal;
Type *type = fiber->code[fiber->ip].type;

(--fiber->top)->ptrVal = (interface->selfType && typeEquivalent(type, interface->selfType)) ? interface->self : NULL;
fiber->ip++;
Expand Down Expand Up @@ -3606,6 +3634,8 @@ static FORCE_INLINE void vmLoop(VM *vm)
case OP_DEREF: doDeref(fiber, error); break;
case OP_ASSIGN: doAssign(fiber, error); break;
case OP_CHANGE_REF_CNT: doChangeRefCnt(fiber, pages); break;
case OP_CHANGE_REF_CNT_GLOBAL: doChangeRefCntGlobal(fiber, pages, error); break;
case OP_CHANGE_REF_CNT_LOCAL: doChangeRefCntLocal(fiber, pages, error); break;
case OP_CHANGE_REF_CNT_ASSIGN: doChangeRefCntAssign(fiber, pages, error); break;
case OP_UNARY: doUnary(fiber, error); break;
case OP_BINARY: doBinary(fiber, pages, error); break;
Expand Down Expand Up @@ -3779,7 +3809,19 @@ int vmAsm(int ip, Instruction *code, DebugInfo *debugPerInstr, char *buf, int si
case OP_ASSERT_TYPE:
{
char typeBuf[DEFAULT_STR_LEN + 1];
chars += snprintf(buf + chars, nonneg(size - chars), " %s", typeSpelling((Type *)instr->operand.ptrVal, typeBuf));
chars += snprintf(buf + chars, nonneg(size - chars), " %s", typeSpelling(instr->type, typeBuf));
break;
}
case OP_CHANGE_REF_CNT_GLOBAL:
{
char typeBuf[DEFAULT_STR_LEN + 1];
chars += snprintf(buf + chars, nonneg(size - chars), " %p %s", instr->operand.ptrVal, typeSpelling(instr->type, typeBuf));
break;
}
case OP_CHANGE_REF_CNT_LOCAL:
{
char typeBuf[DEFAULT_STR_LEN + 1];
chars += snprintf(buf + chars, nonneg(size - chars), " %lld %s", (long long int)instr->operand.intVal, typeSpelling(instr->type, typeBuf));
break;
}
default: break;
Expand All @@ -3788,9 +3830,6 @@ int vmAsm(int ip, Instruction *code, DebugInfo *debugPerInstr, char *buf, int si
if (instr->inlineOpcode == OP_DEREF)
chars += snprintf(buf + chars, nonneg(size - chars), "; DEREF");

else if (instr->inlineOpcode == OP_POP)
chars += snprintf(buf + chars, nonneg(size - chars), "; POP");

return chars;
}

Expand Down
5 changes: 4 additions & 1 deletion src/umka_vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ typedef enum
OP_DEREF,
OP_ASSIGN,
OP_CHANGE_REF_CNT,
OP_CHANGE_REF_CNT_GLOBAL,
OP_CHANGE_REF_CNT_LOCAL,
OP_CHANGE_REF_CNT_ASSIGN,
OP_UNARY,
OP_BINARY,
Expand Down Expand Up @@ -155,7 +157,8 @@ typedef struct
Opcode opcode;
Opcode inlineOpcode; // Inlined instruction (DEREF, POP, SWAP): PUSH + DEREF, CHANGE_REF_CNT + POP, SWAP + ASSIGN etc.
TokenKind tokKind; // Unary/binary operation token
TypeKind typeKind; // Slot type kind
TypeKind typeKind;
Type *type;
Slot operand;
} Instruction;

Expand Down

0 comments on commit c6256a4

Please sign in to comment.