OOL(Out of line)代码是什么?我在ION编译器中发现了它,但无法理解发生了什么。
bool CodeGeneratorShared::generateOutOfLineCode() {
for (size_t i = 0; i < outOfLineCode_.length(); i++) {
// Add native => bytecode mapping entries for OOL sites.
// Not enabled on asm.js yet since asm doesn't contain bytecode mappings.
if (!gen->compilingAsmJS()) {
if (!addNativeToBytecodeEntry(outOfLineCode_[i]->bytecodeSite()))
return false;
}
if (!gen->alloc().ensureBallast())
return false;
JitSpew(JitSpew_Codegen, "# Emitting out of line code");
masm.setFramePushed(outOfLineCode_[i]->framePushed());
lastPC_ = outOfLineCode_[i]->pc();
outOfLineCode_[i]->bind(&masm);
outOfLineCode_[i]->generate(this);
}
return !masm.oom();
}
我尝试使用谷歌找到有关它的信息,但没有取得成功。也许你可以告诉我它是什么?谢谢:))
答案 0 :(得分:2)
我查看了源代码,这里的“out of line”似乎意味着在正常代码/函数之后生成的代码。
参见例如CodeGenerator::generate
基本上看起来像这样:
generateProlog();
generateBody();
generateEpilog();
generateOutOfLineCode();
因此在代码结束后生成了行外代码。这通常用于特殊的控制流,并保持调用去优化,抛出异常等的代码超出指令缓存和“正常”程序代码。
假设我们有一个函数int f(int a, int b) { return a / b; }
,语法语义迫使我们在除数为0时抛出异常。这是伪汇编中的代码:
cmp b, 0
jump-if-not-zero lbl1
call throw_exception
lbl1:
div c, a, b
ret c
您可以看到正常的程序流需要跳过抛出异常的代码。通常b在几乎所有情况下都不为零,因此看起来有点浪费。使用不符合代码的代码,我们可以生成更高效的代码:
cmp b, 0
jump-if-zero out-of-line1
div c, a, b
ret c
out-of-line1:
call throw_exception
这里我们只跳过零值,这应该是罕见的。 cmp
和div
指令也相互靠近,这有利于指令缓存的使用。
在我的JIT中,我为空指针异常抛出,失败断言等生成了行代码.JS和IonMonkey可以将它用于不同的操作。我发现的行外代码的一个示例是WASM的类OutOfLineTruncateF32OrF64ToI32
,它扩展了OutOfLineCode
所有行外代码的基类。
IonMonkey中的异常代码可以使用字段rejoin
跳回正常的代码流,这也很好。