C++ 为什么对';案例';陈述

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

我浏览了SpiderMonkey引擎的源代码,在解释器中看到了一些引起我兴趣的代码

// 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、 如果条件跳转之后通常是返回。谢谢你让我知道。