C++ 为什么对';案例';陈述
我浏览了SpiderMonkey引擎的源代码,在解释器中看到了一些引起我兴趣的代码C++ 为什么对';案例';陈述,c++,C++,我浏览了SpiderMonkey引擎的源代码,在解释器中看到了一些引起我兴趣的代码 // Portable switch-based dispatch. # define INTERPRETER_LOOP() the_switch: switch (switchOp) # define CASE(OP) case OP: # define DEFAULT() default: (来源:) 将case OP:定义为case
// Portable switch-based dispatch.
# define INTERPRETER_LOOP() the_switch: switch (switchOp)
# define CASE(OP) case OP:
# define DEFAULT() default:
(来源:)
将
case OP:
定义为case(OP)
,是否有任何非风格上的好处?如果您在同一源代码中查找更高的位置,对于不同的编译器语法,这些宏有不同的定义:
/*
* Define macros for an interpreter loop. Opcode dispatch may be either by a
* switch statement or by indirect goto (aka a threaded interpreter), depending
* on compiler support.
*
* Threaded interpretation appears to be well-supported by GCC 3 and higher.
* IBM's C compiler when run with the right options (e.g., -qlanglvl=extended)
* also supports threading. Ditto the SunPro C compiler.
*/
#if (defined(__GNUC__) || \
(__IBMC__ >= 700 && defined __IBM_COMPUTED_GOTO) || \
__SUNPRO_C >= 0x570)
// Non-standard but faster indirect-goto-based dispatch.
# define INTERPRETER_LOOP()
# define CASE(OP) label_##OP:
# define DEFAULT() label_default:
# define DISPATCH_TO(OP) goto* addresses[(OP)]
//...
#else
// Portable switch-based dispatch.
# define INTERPRETER_LOOP() the_switch: switch (switchOp)
# define CASE(OP) case OP:
# define DEFAULT() default:
# define DISPATCH_TO(OP) \
JS_BEGIN_MACRO \
switchOp = (OP); \
goto the_switch; \
JS_END_MACRO
// ...
#endif
如果在同一源代码中进一步查看,您将看到实际使用的宏:
INTERPRETER_LOOP() {
CASE(EnableInterruptsPseudoOpcode)
{
//...
DISPATCH_TO(op);
}
* Various 1-byte no-ops. */
CASE(JSOP_NOP)
CASE(JSOP_UNUSED14)
CASE(JSOP_BACKPATCH)
//...
{
//...
ADVANCE_AND_DISPATCH(1);
}
CASE(JSOP_LOOPHEAD)
END_CASE(JSOP_LOOPHEAD)
//...
DEFAULT()
{
//...
goto error;
}
} /* interpreter loop */
根据编译器的不同,该代码将编译为:
static const void* const addresses[EnableInterruptsPseudoOpcode + 1] = {
...
};
...
{
label_EnableInterruptsPseudoOpcode:
{
//...
goto* addresses[op];
}
* Various 1-byte no-ops. */
label_JSOP_NOP:
label_JSOP_UNUSED14:
label_JSOP_BACKPATCH:
//...
{
//...
REGS.pc += 1;
SANITY_CHECKS();
goto* addresses[*REGS.pc | activation.opMask()];
}
label_JSOP_LOOPHEAD:
goto* addresses[JSOP_LOOPHEAD_LENGTH];
//...
label_default:
{
//...
goto error;
}
} /* interpreter loop */
或为此:
jsbytecode switchOp;
...
the_switch:
switch (switchOp) {
case EnableInterruptsPseudoOpcode:
{
//...
switchOp = op;
goto the_switch;
}
* Various 1-byte no-ops. */
case JSOP_NOP:
case JSOP_UNUSED14:
case JSOP_BACKPATCH:
//...
{
//...
REGS.pc += 1;
SANITY_CHECKS();
switchOp = *REGS.pc | activation.opMask;
goto the_switch;
}
case JSOP_LOOPHEAD:
REGS.pc += JSOP_LOOPHEAD_LENGTH;
SANITY_CHECKS();
switchOp = *REGS.pc | activation.opMask();
goto the_switch;
//...
default:
{
//...
goto error;
}
} /* interpreter loop */
半屏:
#if (defined(__GNUC__) || \
(__IBMC__ >= 700 && defined __IBM_COMPUTED_GOTO) || \
__SUNPRO_C >= 0x570)
// Non-standard but faster indirect-goto-based dispatch.
# define INTERPRETER_LOOP()
# define CASE(OP) label_##OP:
// ... <snip>
#else
// Portable switch-based dispatch.
# define INTERPRETER_LOOP() the_switch: switch (switchOp)
# define CASE(OP) case OP:
// ... <snip>
#endif
#如果(定义的(uu GNUC_uu)|\
(uuu IBMC_uuu>=700&&defined_uuuibm_COMPUTED_GOTO)|\
__SUNPRO_C>=0x570)
//非标准但更快的基于goto的间接调度。
#定义解释器_循环()
#定义案例(OP)标签35;#OP:
// ...
#否则
//基于便携式交换机的调度。
#定义解释器\u LOOP()\u开关:开关(switchOp)
#定义案例(OP)案例OP:
// ...
#恩迪夫
GCC和其他一些编译器支持,但不是标准的,因此不可移植
如果编译器支持计算转到,则此
#If
的第一个分支定义解释器_循环
,CASE(OP)
等以使用计算转到;否则,#else
分支会根据标准设施对其进行定义。如果您真的想知道他们为什么使用此功能的详细信息,请阅读本出版物,谢谢。我没有理解替代的定义,这现在是有意义的。但是,如果可能的话,编译器不是已经优化了开关用例以计算goto吗?为什么需要这样做?@LưuVĩnhPhúc问得好;Eli Bendersky在上面链接的文章中讨论了这一点。首先,计算goto可以省略边界检查,但另一个区别是开关从单个位置跳转,而计算goto从不同位置跳转,因此分支预测器可以“学习”操作码的行为;e、 如果条件跳转之后通常是返回。谢谢你让我知道。