在控制语句的指令生成过程中, 语句无法知道外界指令结构, 不能贸然将跳出语句定向到外部指令, 因此使用了 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, 不过不保证, 哈~
清理NOP指令优化编译器
本文介绍了一种编译器优化方法,通过记录NOP指令后的首个非NOP指令索引,重新定向跳转目标并删除所有NOP指令,有效提升了编译代码的执行效率。
2361

被折叠的 条评论
为什么被折叠?



