随着讨论这里,javac的和其他Java编译器可以提供代码消除能力if-statements这里的条件是"常量表达式".
如果我的代码使用依赖于不同包中定义的其他常量表达式的常量表达式,这会受到什么影响?
例如,假设我在相应的指定包中有以下类:
package foo;
public class Foo {
public static final boolean CONDITION = false;
}
Run Code Online (Sandbox Code Playgroud)
和
package bar;
import foo.Foo;
public class Bar {
public void test() {
if (Foo.CONDITION) {
System.out.println("This line of code could be eliminated.");
} else {
System.out.println("This line of code will be executed.");
}
}
}
Run Code Online (Sandbox Code Playgroud)
显然,如果foo-package是在从外部JAR文件运行时加载,编译器不能在技术上只是假设,Foo.CONDITION将是错误的,不应该消除true的分枝的if语句来.
然而,如果Foo并且Bar实际上在同一个包中,则true应该绝对消除-branch(如果编译器完全支持代码消除).
不太确定如何最好短语这个问题,但:如何"亲密"也Foo必须是Bar常量表达式在 …
java compiler-construction dead-code constant-expression code-elimination
我很难找到有关javac代码消除功能的信息:
我读到如果你有类似下面这样的东西,那么if-statement将被淘汰:
static final boolean DEBUG = false;
if (DEBUG) System.out.println("Hello World!"); // will be removed
Run Code Online (Sandbox Code Playgroud)
但是这个怎么样,例如:
static final int VALUE = 3;
if (VALUE > 9) System.out.println("VALUE > 9 ???"); // will this be removed?
Run Code Online (Sandbox Code Playgroud)
或这个:
static final SomeEnum VALUE = SomeEnum.FOO;
if (VALUE==SomeEnum.BAR) System.out.println("Bar???"); // will this be removed?
Run Code Online (Sandbox Code Playgroud)
由于分析程序以查找所有死代码(可能类似于暂停问题)非常困难/不可能,因此我认为只有少数明确定义的构造(如上面的第一个示例),javac它将识别并删除可靠.是否有这些结构的完整列表?
我使用 Vite 捆绑器,在我的代码中我有以下功能:
function doSomething() {
if (!import.meta.env.VITE_SOMETHING) {
return;
}
console.log("Hello");
}
Run Code Online (Sandbox Code Playgroud)
我希望在构建我的应用程序(npm run build)而不定义VITE_SOMETHING环境变量后,我将Hello在代码中看到没有日志记录,但我看到了。
更糟糕的是,在我使用的每个地方,import.meta.env.VITE_SOMETHING我都在编译的输出中看到{BASE_URL:"/",MODE:"production",DEV:!1,PROD:!0}.VITE_SOMETHING。它看起来不是很理想。
是否可以共同配置 Vite 来优化输出 - 删除未使用的代码和重复项(它引入的)?
虽然使用 goto进行翻译很容易(如f.ex.IL所示),但我想知道是否也可以使用更高级别的表达式和语句来消除所有 goto语句 - 比如说 - 使用Java支持的所有内容.
或者如果您愿意:我正在寻找的是"重写规则",无论创建goto的方式如何,它都将始终有效.
它主要是作为一个理论问题,纯粹是作为利益; 不是好/坏的做法.
我想到的显而易见的解决方案是使用这样的东西:
while (true)
{
switch (state) {
case [label]: // here's where all your goto's will be
state = [label];
continue;
default:
// here's the rest of the program.
}
}
Run Code Online (Sandbox Code Playgroud)
虽然这可能会起作用并且确实符合我的"正式"问题,但我不喜欢我的解决方案.对于其中一个,它已经死了,而且对于两个,它基本上将goto包装成一个与goto完全相同的开关.
那么,有更好的解决方案吗?
更新1
由于很多人似乎认为这个问题"过于宽泛",我将详细说明......我之所以提到Java,是因为Java没有'goto'语句.作为我的一个业余爱好项目,我试图将C#代码转换为Java,这被证明是非常具有挑战性的(部分原因是Java中的这种限制).
这让我思考.如果你有f.ex. 在Open寻址中实现'remove'方法(参见:http://en.wikipedia.org/wiki/Open_addressing-注1),在特殊情况下使用'goto'非常方便,尽管在这个特殊情况下你可以通过引入一个'state'变量来重写它.请注意,这只是一个例子,我已经为连续实现了代码生成器,当你试图对它们进行反编译时会生成大量的goto.
我也不确定在这个问题上的重写是否总是会消除'goto'语句,如果在每种情况下都允许的话.虽然我不是在寻找正式的"证据",但有些证据表明在这个问题上可以消除这种证据会很棒.
所以关于'广泛性',我挑战所有认为有'太多答案'或'很多方法重写goto'以提供算法或方法重写一般情况的人,因为我发现的唯一答案到目前为止我发布的那个.
假设 V8 将完全消除死代码(结构如下)是否正确?
export const DEBUG = false
Run Code Online (Sandbox Code Playgroud)
import { DEBUG } from './module1.js'
if (DEBUG) {
// dead code eliminated?
}
Run Code Online (Sandbox Code Playgroud)
请不要评论“‘if’检查的开销非常小,你应该 XXX 而不是问这个问题”。我只是想知道 V8 是否能够做到这一点(是/否,当然最好有一些细节)。