[优化]删去 NOP 指令

在控制语句的指令生成过程中, 语句无法知道外界指令结构, 不能贸然将跳出语句定向到外部指令, 因此使用了 NOP 指令缓冲了这些跳转. 然而, 在全部指令生成结束后, 跳转指令就可以根据上下文选择正确的目标了, 那么 NOP 指令只是影响性能的冗余指令了. 本着兔死狗烹的原则, 现在去掉这些指令.

static void cleanNop(struct List* instructions);

具体的做法是, 为每个 NOP 指令记录它之后的第一条非 NOP 指令, 然后扫描指令序列, 重定向它们的目标, 然后删去全部 NOP 指令. 现在先给指令数据结构增加一个索引域

/* 增加 index 域 */
#define memberAbstractInstruction \
    int segOffset;                \
    int index;                    \
    InstructionCode code; /*******/
struct AbstractInstruction {
    memberAbstractInstruction
};

对于非 NOP 指令, 它的索引域等于它自己的位置索引, 而 NOP 指令的索引域等于该指令之后第一条非 NOP 指令的索引.

对整个指令序列进行一次逆向遍历, 计算它们的索引值

    int index = instructions->count(instructions) - 1;
    int lastOpInd;
    struct AbstractInstruction* ins;
    for (; index >=0; --index) {
        ins = (struct AbstractInstruction*)
              (instructions->elementAt(instructions, index));
        if (NOP != ins->code) {
            lastOpInd = index;
        }
        ins->index = lastOpInd;
    }

扫描并重定向全部的跳转指令

    struct Iterator* iterator;
    for_each (iterator, instructions) {
        ins = (struct AbstractInstruction*)(iterator->current(iterator));
        if (isJump(ins->code)) {
            struct JumpInstruction* jmp = (struct JumpInstruction*)ins;
            jmp->targetIns = instructions->elementAt(instructions,
                                                     jmp->targetIns->index);
        }
    }

删除 NOP 指令. 任务完成.

    for_each (iterator, instructions) {
        if (NOP == ((struct AbstractInstruction*)
                    (iterator->current(iterator)))->code) {
            revert(iterator->current(iterator));
            iterator->remove(iterator);
        }
    }

 

现在的修改版本中, 输出指令的代码被移入新文件, 减少了 jerry-compiler.c 的混乱程度.

void fakeDefaultAnalyserConsumeNT(void* self, struct AbstractSyntaxNode* node)
{
    if (NULL == node) {
        return;
    }

    node = (struct AbstractSyntaxNode*)newBasicBlockNode(node);
    initStack(&loopStack);
    initialSymTabManager();
    struct List* insList = node->createInstruction(node);
    node->delNode(node);
    finalizeSymTabManager();
    loopStack.finalize(&loopStack);
    if (isFailed()) {
        while (0 != insList->count(insList)) {
            revert(insList->popElementAt(insList, 0));
        }
        cresult = ERROR_IN_SRC;
        return;
    }

    struct NoParamInstruction* endProg = (struct NoParamInstruction*)
                                    allocate(sizeof(struct NoParamInstruction));
    endProg->code = END_PROGRAM;
    insList->addTo(insList, endProg, insList->count(insList));
    /* 原先在这里的代码, 以及 writeInstruction 函数被移入了
       instruction-process.cpp / instruction-process.h */
    ErrMsg err = processIns(insList, treeout);
    if (NULL != err) {
        fputs(err, stderr);
        cresult = IO_ERROR;
    }
    insList->finalize(insList);
}

 

编译器/解释器构造到此结束, 也许我还会改改 Jerry, 不过不保证, 哈~

你可能感兴趣的:(数据结构,虚拟机)